看看文档中的内容:
type ErrorAndStateWithIO e s a = ErrorT e (StateT s IO) a
==> ErrorT (StateT s IO (Either e a))
==> ErrorT (StateT (s -> IO (Either e a,s)))
我还附上了ErrorT
:的构造函数
Constructors
ErrorT
runErrorT :: m (Either e a)
我不能理解的是我帖子顶部的一件事。这是什么意思?对我来说,这意味着ErrorT e (StateT s IO) a = ErrorT (StateT s IO (Either e a))
。怎么了?它有点像自动调用构造函数(runErrorT
)?
困扰我的第二件事是:我们知道StateT
的形式是StateT s m a
。这里,我们有StateT s IO
。a
参数在哪里?
最后一件事——有人能解释一下如何运行这个monad吗?
文档的作者在记法方面反复无常。他们用它们的构造函数替换类型ErrorT
和StateT
,它们也有名称ErrorT
和StateT
。(这有一定的道理,因为它们是newtype
s。)作者试图指出的是,ErrorAndStateWithIO e s a
等价于s -> IO (Either e a, s)
;它周围只有几个newtype
包装
看看这些类型的定义,
newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
您可以看到,在第一步中,外部ErrorT
已被其定义替换,在第二步中,内部StateT
已被其含义替换。
这里,我们有
StateT s IO
。a
参数在哪里?
ErrorT e
是一个单声道转换器,这意味着它将单声道转换为其他单声道。君主总是有一种* -> *
;monad变压器有一种CCD_ 22。CCD_ 23也是一个monad变换器。这里,StateT s
被应用于IO
以产生新的monad(其是用状态管理能力增强的IO
),然后ErrorT e
被应用于其以产生另一个monad(它是用错误处理能力增强的StateT s IO
)。
有人能解释一下如何运行这个monad吗?
正如我上面提到的,ErrorAndStateWithIO e s a
只是s -> IO (Either e a, s)
,它周围有几个newtype
包装器。所以要运行它,你需要打开newtype
,传递一个s
,将其垂直放入IO计算中,并仔细检查结果。
myComputation :: ErrorAndStateWithIO String Int Char
myComputation = -- ...
main = do
(result, _) <- runStateT (runErrorT myComputation) 5
case result of
Left err -> putStrLn err
Right result -> putStrLn $ "Success: " ++ [result]