我有这个Haskell代码部分:
newtype State st a = State (st -> (st, a))
instance Monad (State state) where
return x = let f t = (t,x) in State f
State f >>= g = State (\oldstate ->
let {(newstate, val) = f oldstate;
State f'= g val}
in f' newstate)
我是monad的新手,但我想我得到了return
和bind
在一般情况下的工作方式。
但是在上面的例子中我有很多问题:
Monad (State state)
中的newtype State ...
?return x = let f t = (t,x) in State f
t
来自哪里?答案 0 :(得分:8)
所以到目前为止,你肯定听说过 currying 或部分应用:如果你有f :: a -> b -> c
和x :: a
,那么f x :: b -> c
。即,如果f
是双参数函数而x
具有类型f
的第一个参数,则f x
是一个函数,它采用第二个参数参数和"完成"申请。
好吧,在Haskell中,同样的事情适用于像State
这样的类型构造函数。类型和类型构造函数具有种类,类似于值具有类型的方式。像Integer
这样的非参数类型具有种类*
;像Maybe
这样的单参数类型有* -> *
种; State
有* -> * -> *
种。
然后,State state
是State
类型构造函数的部分应用,并且有* -> *
种。 Monad
是适用于* -> *
种类的类。所以,适用于我们的例子:
instance Monad (Integer) where ...
被禁止,因为Integer
有*
种。instance Monad (Maybe) where ...
是允许的,因为Maybe
有* -> *
种。instance Monad (State) where ...
被禁止,因为State
有* -> * -> *
种。instance Monad (State st) where ...
是允许的,因为State st
有* -> *
种。我们如何知道Monad
适用于* -> *
类型?我们可以从类声明中推断它:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
-- ...
查看此类声明中m
的使用方式:作为m a
和m b
的一部分,即采用一个参数。因此,Haskell推断m
是类* -> *
的类型变量。
与此相比:
class Num a where
(+) :: a -> a -> a
(-) :: a -> a -> a
-- ...
此处类型变量a
未应用于其他类型变量 - 因此它必须是*
种类。
严格来说,State
不是一个单子;它是一个两位类型的构造函数,当部分应用于一种类型时,它会为你提供一个monad。所以State state
是一个monad,就像State Integer
,State [a]
等一样。人们常常会松散地谈论State
和类似monad的事情,但你应该理解它是一个参数化的 monad-it&a; monad,它有一个内部类型参数,因此许多变体在该参数的类型上有所不同。
答案 1 :(得分:1)
State
是monad的类型,instance Monad (State state)
声明State state
(其中state
是一个类型变量,可以设置为任何其他类型*) Monad
的一个实例。 newtype State
是State
类型的定义。let f t = (t, x)
正在定义函数,其参数名为t
。 *从技术上讲,state
是类型*
的类型变量,但不要担心。