簡體   English   中英

如何使用自定義 App 類型代替 IO?

[英]How to use custom App type in place of IO?

我想在我的程序中使用自定義應用程序類型代替IO ,並將它與來自async庫的race_功能race_使用。

具體來說,我熱衷於將App類型的兩個計算傳遞給race_ 由於race_只接受IO類型的值,我用return包裝了這些計算。

雖然進行了類型檢查,但我可以看到實際上沒有執行任何計算。

這是一個說明問題的最小示例¹:

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables        #-}

module RaceTest where

import           Control.Monad.Reader           ( MonadReader
                                                , ReaderT(..)
                                                , runReaderT
                                                )
import           Control.Monad.IO.Class         ( MonadIO
                                                , liftIO
                                                )
import           Control.Concurrent.Async       ( race_ )

data Env = Env { val :: !Int }

newtype App a = App
    { unApp :: ReaderT Env IO a
    } deriving (Functor, Applicative, Monad, MonadIO, MonadReader Env)

runApp :: Env -> App a -> IO a
runApp env app = runReaderT (unApp app) env

main = runApp (Env 24) simpleApp
 where
   simpleApp :: App () = do
     liftIO $ putStrLn "About to spawn threads"
     liftIO $ race_ (return firstAsync) (return secondAsync)
   firstAsync  :: App () = liftIO $ putStrLn "First async"
   secondAsync :: App () = liftIO $ putStrLn "Second async"

如何使用race_運行這些App類型的計算?


¹雖然在本示例中刪除App類型很簡單,但在我正在構建的應用程序中,我有AppEnv類型,允許使用類似於此設置的co-log進行日志記錄。 這是我不想失去的東西。

您的計算沒有得到執行,因為您實際上並沒有將它們傳遞給race_ 相反,您傳遞了兩個IO計算,它們作為結果返回您的App計算。 但不執行它們。

為了讓它們在IO內執行,請使用您已有的函數runApp 由於您需要將環境傳遞給它,並且我假設您希望使用與simpleApp本身相同的環境,因此您可以使用askMonadReader上下文中獲取它:

simpleApp :: App () = do
     liftIO $ putStrLn "About to spawn threads"
     env <- ask
     liftIO $ race_ (runApp env firstAsync) (runApp env secondAsync)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM