如何处理 Monad、Functor 和 Applicative 来编写有状态代码

问题描述 投票:0回答:1

我正在尝试用 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
                          ^^^^^

我在这里缺少什么?

haskell functional-programming monads functor
1个回答
0
投票

与为

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
实例仍然需要手动定义。

© www.soinside.com 2019 - 2024. All rights reserved.