haskell,如何处理不匹配的类型-单子
我无法处理以下问题:haskell,如何处理不匹配的类型-单子,haskell,monads,Haskell,Monads,我无法处理以下问题: 我有一些函数,返回foo::a->b->error String IO Int 我知道它返回IO(字符串Int中的任意一个) 然而,我还有一个更复杂的函数,返回: bar::a->b->StateT Char(ReaderT Char(error String IO))Int 此函数bar调用函数foo。我要做以下事情: 如果foo调用throwerrbar也会抛出相同的错误。如果foo返回Intbar也返回Int 但是,由于类型不匹配,这是可能的 我不知道如何优雅地做到这
我有一些函数,返回
foo::a->b->error String IO Int
我知道它返回
IO(字符串Int中的任意一个)
然而,我还有一个更复杂的函数,返回:
bar::a->b->StateT Char(ReaderT Char(error String IO))Int
此函数bar
调用函数foo
。我要做以下事情:如果
foo
调用throwerr
bar
也会抛出相同的错误。如果foo
返回Int
bar
也返回Int
但是,由于类型不匹配,这是可能的
我不知道如何优雅地做到这一点。
我认为我的变换器monad的顺序不正确 像这样的方法应该会奏效:
bar x y = do
-- some code
z <- lift $ lift $ foo x y
-- some more code
return z
bar x y=do
--一些代码
z我通常使用我称之为Transformer Monad的类:
最后一件可能不明显的事情是,outer
的签名也可以用通用的方式表示:
outer :: (MonadState Char m, MonadReader Char m, MonadIO m) => m Int
而且它在没有电梯的情况下仍然可以工作(对于IO操作,无liftIO
,因为像print
这样的函数是根据IO
定义的,而不是MonadIO m
。相比之下,像ask
和get
这样的函数是根据相应的MonadX
类定义的,这允许我们跳过提升).你可以添加一个例子,在bar
内调用foo
-你可能需要正确的提升?是的,非常感谢。我使用了lift$lift$
,编译器接受了它。我不知道-我认为提升将以自动方式完成。这将使使用monad堆栈变得更容易;)-但没关系-也许你想写下自己的答案,或者在问题解决后关闭问题,而不是使用具体的类型,使用MonadState
、MonadError
和MonadError
-这样你就不必提起了。
outer' :: ErrorT String (StateT Char (ReaderT Char IO)) Int
outer' = do
a <- inner' -- still no need to lift!
b <- lift . lift $ inner -- need to double lift in this case
return 5
outer :: (MonadState Char m, MonadReader Char m, MonadIO m) => m Int