我正在尝试用 Haskell 编写一些有状态代码。为此,我遵循此材料。至此,我已经了解了 monad 和 functor,粗略地说,我很困惑,无法在材料上取得进展。我有这个M(非)WE:
import Control.Monad
data State s a = State (s -> (a,s))
runState (State f) s = f s
put :: s -> State s ()
put state = State (\oldState -> ((), state))
get :: State s s
get = State (\state -> (state,state))
modify :: (s -> s) -> State s ()
modify f = State (\state -> ((), f state))
-- The following 3 rows fail:
instance Functor State where
fmap f (State s) = State (f x)
-- The following 3 rows fail:
instance Applicative State where
pure = return
(<*>) = ap
instance Monad (State s) where
return x = State (\s -> (x,s))
op >>= f = State h
where h state0 = let (val,state1) = runState op state0
op2 = f val
in runState op2 state1
add :: Int -> State Int ()
add i = do old <- get
put (old+i)
main = do
print(runState (add 1 >> add 3 >> add 5 >> add 6) 0)
错误信息是:
question1.hs:16:18: error:
* Expecting one more argument to `State'
Expected kind `* -> *', but `State' has kind `* -> * -> *'
* In the first argument of `Functor', namely `State'
In the instance declaration for `Functor State'
|
16 | instance Functor State where
| ^^^^^
question1.hs:19:22: error:
* Expecting one more argument to `State'
Expected kind `* -> *', but `State' has kind `* -> * -> *'
* In the first argument of `Applicative', namely `State'
In the instance declaration for `Applicative State'
|
19 | instance Applicative State where
^^^^^
我在这里缺少什么?
与为
Monad
定义 State s
实例的方式相同:
instance Monad (State s) where ...
必须为
Functor
定义 Applicative
和 State s
实例:
instance Functor (State s) where ...
instance Applicative (State s) where
仅供参考,错误消息指的是 Functor
和
Applicative
约束适用于具有
* -> *
类型的类型。这是一种接受单个类型参数来给出类型的“类型函数”,就像
Maybe
接受单个类型参数一样,例如
Int
来给出类型
Maybe Int
。 (这就是为什么
Maybe
可以是有效的
Functor
/
Applicative
/
Monad
- 它具有正确的类型
* -> *
。)当您尝试将
State
本身设为
Functor
或
Applicative
时,种类不对。类型函数
State
具有 kind
* -> * -> *
的意思,它需要两个参数来形成一个类型,就像 add 函数的返回类型
State Int ()
一样。另一方面,
State s
具有正确的类型
* -> *
,因为它只需要应用于另一种类型(例如,
State s a
)即可形成类型。一旦修复了这些错误,您将遇到另一个错误,因为您的
fmap
定义是错误的:
fmap f (State s) = State (f x)
此处,x
未定义。您需要做的是利用左侧的
s
变量,它是
s -> (a,s)
类型的函数来构造右侧,类似于您在中定义
>>=
的方式Monad
实例。以下有剧透...
.
.
.
以下内容将起作用,尽管我已将此变量重命名为
act
(状态“动作”的缩写),以避免将其与状态本身混淆:
fmap f (State act) = State (\s -> let (a, s') = act s in (f a, s'))
或者,Functor
实例可以自动派生(并且总是只有一个正确的派生),因此您可以打开正确的扩展并添加派生子句:
{-# LANGUAGE DeriveFunctor #-}
...
data State s a = State (s -> (a,s))
deriving (Functor)
然后完全删除 Functor
实例。但是,
Applicative
和
Monad
实例仍然需要手动定义。