gpt4 book ai didi

haskell - 如何使用自定义App类型代替IO?

转载 作者:行者123 更新时间:2023-12-02 17:31:50 25 4
gpt4 key购买 nike

我想在程序中使用自定义应用程序类型来代替 IO,并将其与 race_ 等函数一起使用。来自 async 库。

具体来说,我热衷于将 App 类型的两个计算传递给 race_。由于 race_ 仅接受 IO 类型的值,因此我用 return 包装了这些计算。

在进行类型检查时,我可以看到这两个计算都没有实际执行。

这是一个说明问题的最小示例 1:

{-# 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 和允许使用与此类似的 co-log 进行日志记录的 Env 类型 setup 。这是我不想失去的东西。

最佳答案

您的计算没有被执行,因为您实际上没有将它们传递给 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)

关于haskell - 如何使用自定义App类型代替IO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60018048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com