【发布时间】:2020-05-06 18:22:57
【问题描述】:
假设我有这样的环境记录:
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
type RIO env a = ReaderT env IO a
data Env = Env
{ foo :: Int -> String -> RIO Env (),
bar :: Int -> RIO Env Int
}
env :: Env
env =
Env
{ foo = \_ _ -> do
liftIO $ putStrLn "foo",
bar = \_ -> do
liftIO $ putStrLn "bar"
return 5
}
存储在环境中的函数可能有不同数量的参数,但它们总是会在 RIO Env monad 中产生值,也就是说,在 ReaderT 中超过 IO 由环境本身参数化。
我想在RIO Env monad 中以简洁的方式调用这些函数。
我可以写这样的call函数:
import Control.Monad.Reader
call :: MonadReader env m => (env -> f) -> (f -> m r) -> m r
call getter execute = do
f <- asks getter
execute f
并像这样使用它(可能与-XBlockArguments结合使用):
example1 :: RIO Env ()
example1 = call foo $ \f -> f 0 "fooarg"
但是,理想情况下,我希望有一个 call 版本,它允许以下更直接的语法,并且仍然适用于具有不同数量参数的函数:
example2 :: RIO Env ()
example2 = call foo 0 "fooarg"
example3 :: RIO Env Int
example3 = call bar 3
这可能吗?
【问题讨论】: