Haskell如何知道每个return
表达式的哪个是正确的monad实例?
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . return
答案 0 :(得分:4)
它推断出所需的类型。
从instance
定义的含义可以清楚地看出,我们正试图定义
returnMaybeT :: Monad m => a -> MaybeT m a
returnMaybeT x = MaybeT (return (return x))
从MaybeT :: m (Maybe a) -> MaybeT a
(作为函数)我们知道return
的内部堆栈必须具有类型
return (return x) :: Monad m => a -> m (Maybe a)
现在,我们知道return
是一个多态函数,其类型为
return :: a -> n a
任何 Monad
n
。对于第一个return
,Monad m =>
约束告诉我们m
是Monad
,因此我们可以使用其返回定义。这让我们可以一直到内部return
return x :: a -> Maybe a
由于我们知道Maybe
有一个Monad
个实例,我们可以使用return
。
最终,所有编译器必须做的就是试图确定每个return
所需的类型。确定所需类型后,必须检查它是否知道该类型的Monad
实例。这对于Maybe
来说很简单,因为它是具体的,但m
更难看,因为它只是一个变量。
m
的作用原因是因为我们已将变量约束为某些类型,该类型实例化Monad
。
答案 1 :(得分:4)
这实际上与上下文无关。
让我们玩typechecker,
-- From the signature
MaybeT . return . return :: a -> MaybeT a
-- From the type of MaybeT
return . return :: a -> m (Maybe a)
-- From the type of `.`
(return :: Maybe a -> m a) . (return :: a -> Maybe a)
一旦我们得到每个return
的类型,“实例选择算法”将正确选择第一个使用m
s return
,第二个使用Maybe
}。