![](/img/trans.png)
[英]How do I use map over a list with do notation - ie avoid type `IO ()' with type `[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
類型很簡單,但在我正在構建的應用程序中,我有App
和Env
類型,允許使用類似於此設置的co-log
進行日志記錄。 這是我不想失去的東西。
您的計算沒有得到執行,因為您實際上並沒有將它們傳遞給race_
。 相反,您傳遞了兩個IO
計算,它們作為結果返回您的App
計算。 但不執行它們。
為了讓它們在IO
內執行,請使用您已有的函數runApp
。 由於您需要將環境傳遞給它,並且我假設您希望使用與simpleApp
本身相同的環境,因此您可以使用ask
從MonadReader
上下文中獲取它:
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.