我对输入正确的事实感到失望:
renumberTree2' :: Tree a -> StateT Int Identity (Tree Int)
renumberTree2' t = get >>= (\v -> return (Empty))
毕竟,我们有:
(>>=) :: m a -> (a -> m b) -> m b
。由于StateT s m a
我们无法绑定get :: StateT s m s
这一事实。 get不是m a
类型的预期bind
但是,get s
其中s :: s->(a, s')
是正确的类型,应该给予绑定。我哪里错了?
答案 0 :(得分:6)
你在阅读类型时错了。您可以像处理优先级的函数一样处理更高级的kinded类型(具有类型参数的类型)。如果你有一个功能
f :: a -> b -> c -> d -> e
f a b c d = undefined
然后调用它
let e = f a b c d
相当于
let e = (((f a) b) c) d
f a :: b -> c -> d -> e
以及(f a) b
等等
当您看到类型StateT s m a
时,您也可以将其视为((StateT s) m) a
,类型是等效的,GHC会乐意接受该语法。通过这种方式,可以更轻松地了解Monad m => StateT s m a
与Monad m' => m' a'
的对齐方式:
m' ~ StateT s m
a' ~ a
这意味着有问题的Monad m'
为StateT s m
。一个更简单的示例以完全相同的方式工作,是Functor
的{{1}}实例。 Either a
实例不是Either
,而是Functor
,因为Either a
是类型为Functor
的类型,这意味着只有* -> *
类型一种类型的参数。
答案 1 :(得分:2)
毕竟,我们有:
(>>=) :: m a -> (a -> m b) -> m b
> :type (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
真。
get不符合预期[{1}}类型[by] bind。
m a
不,> import Control.Monad.State
> :type get
get :: MonadState s m => m s
属于get
类型(虽然它确实带有约束)。
答案 2 :(得分:1)
get
的类型为m s
,其中s
是州类型。 MonadState
的{{1}}实例具有上下文:
StateT
所以monad类型Monad m => MonadState s (StateT s m)
是m
。因此,StateT s m
的{{1}}类型为:
get
StateT
的函数必须为某些结果类型(StateT s m) s
添加(>>=)
类型。
s -> StateT s m b
由于b
是monad,的类型为return (Empty)
。