我有这个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)
Run Code Online (Sandbox Code Playgroud)
我是新来的单子,但我想我如何return和bind在一般情况下工作.
但在上面的例子中我有很多问题:
Monad (State state)状态Monad的名字?它与它有什么关系newtype State ...?return x = let f t = (t,x) in State f哪里t来自?因此,通过这一点,你当然听说过的钻营或部分应用程序:如果你有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
-- ...
Run Code Online (Sandbox Code Playgroud)
看看如何m在这个类中声明使用:作为的一部分m a和m b,即作为带一个参数.因此,Haskell推断出这m是一种类型变量* -> *.
与此相比:
class Num a where
(+) :: a -> a -> a
(-) :: a -> a -> a
-- ...
Run Code Online (Sandbox Code Playgroud)
这里的类型变量a不适用于其他类型变量 - 因此它必须是实物*.
所以严格来说,State不是一个单子; 它是一个两位类型的构造函数,当部分应用于一种类型时,它会为您提供一个monad.所以State state是一个monad,就像是State Integer,State [a]等等.人们经常说话松散,谈论State和monad类似的东西,但是你应该理解它是一个参数化的 monad-它是一个monad,它有一个内部类型参数,因此很多变种,该参数的类型不同.