Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
haskell,如何处理不匹配的类型-单子_Haskell_Monads - Fatal编程技术网

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