Предположим, у меня есть такая запись среды:
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
, то есть , в ReaderT
поверх IO
, параметризованного самой средой.
Я хотел бы иметь краткий способ вызова этих функций внутри монады RIO Env
.
Я мог бы напишите что-то вроде этой 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
Возможно ли это?