类型推断似乎是一种魔力

时间:2017-09-25 08:47:14

标签: haskell

我有以下代码段,无法配置它,它是如何工作的:

embedded :: MaybeT (ExceptT String (ReaderT () IO)) Int
embedded = return 1

如何才能只提供一个数字并获得类型签名?编译器如何做到这一点?

1 个答案:

答案 0 :(得分:10)

措辞的选择有点不幸。表达式return 1 不会返回类型签名MaybeT (ExceptT String (ReaderT () IO)) Int

正如 n.m。在评论中写道,如果你不提供类型,表达式会更加通用:

Prelude> embedded = return 1
Prelude> :type embedded
embedded :: (Num a, Monad m) => m a

通过使用类型进行注释,您明确声明您想要的东西不是那么普通。

具体而言,您声明您需要类型MaybeT (ExceptT String (ReaderT () IO)) Int

return如何运作?当MaybeT m aMonad时,mMonadreturn的定义如下:

return = lift . return

右侧returnreturn函数,属于'内部' Monad,而liftMonadTrans定义,并将基础monadic值提升至MaybeT

这解释了如何创建MaybeT值,但不是整个故事。

在这种情况下,'内部' MonadExceptT String (ReaderT () IO),这是另一个Monad(实际上是另一个MonadTrans)。 return的定义如下:

return a = ExceptT $ return (Right a)

请注意,这是另一个嵌套return,其中右侧return属于另一个嵌套Monad

在这种情况下,嵌套的MonadReaderT () IO - 另一个MonadTrans。它定义return,如下所示:

return   = lift . return

另一个嵌套return,其中右侧return是为return定义的IO(在此特定情况下)。

所有这些都是使用a进行参数化的,在这种情况下,您已限制为Int

因此return 1首先获取纯值1并将其打包在IO Int中。然后将其提升到ReaderT () IO Int,再次打包成ExceptT String (ReaderT () IO) Int。最后,这些值被提升到MaybeT