有状态版本的地图(Haskell)

Mas*_*eey 2 haskell higher-order-functions

我刚学会了创建高阶函数,并且我想创建一个map函数,该函数能够更改应用于元组的函数,以使该函数应用于该类型的列表.(就像map函数一样.)我试图以这样的方式创建它:它有这个签名:

statefulMap :: ((a,state) -> (b,state)) -> (([a],state) -> ([b],state))
Run Code Online (Sandbox Code Playgroud)

我希望能够使用此函数创建一系列完整加法器,但是如何创建此函数呢?

Wil*_*sem 6

这实际上已经存在:我们可以使用状态monad并使用monadic版本map:mapM.

例如,我们可以为完整加法器编写函数.在这里,我认为状态是指前一个完整加法器生成的进位.

所以我们可以做一个完整的加法器:

import Control.Monad.State.Lazy

fa :: (Bool, Bool) -> State Bool Bool
fa (a, b) = do
   ci <- get
   let d = a /= b
   put ((ci && d) || (a && b))
   return (ci /= d)
Run Code Online (Sandbox Code Playgroud)

类型意味着我们创建一个改变状态的函数.第一个Bool指定状态本身的类型(这里是布尔值,即,True或者是False),第二个Bool指定我们"返回"的内容(这里是特定全加器的输出TrueFalse输出).

现在我们可以创建一个有状态的地图,其中mapM:

fullAdders :: [(Bool, Bool)] -> State Bool [Bool]
fullAdders = mapM fa
Run Code Online (Sandbox Code Playgroud)

这样就得到了一个2元组的列表(每个全加器的输入),并产生一个State Bool [Bool],所以状态仍然是a Bool,但结果现在是一个布尔[Bool]列表:一个包含每个完整加法器输出的列表.

我们现在可以调用它,fullAdders [(True, True), (True, False), (False, False), (True, True)]但这不会给我们一个布尔值列表,但是a State Bool [Bool].我们可以通过指定初始状态来" 运行 "状态monad.我们可以通过使用来实现runState :: State a b -> a -> (a, b),所以我们可以用它来调用它:

runState (fullAdders [(True, True), (True, False), (False, False), (True, True)]) False
Run Code Online (Sandbox Code Playgroud)

这会产生:

Prelude Control.Monad.State.Lazy> runState (fullAdders [(True, True), (True, False), (False, False), (True, True)]) False
([False,False,True,False],True)
Run Code Online (Sandbox Code Playgroud)

所以一个2元组作为第一项结果,第二项作为新状态(这里True,因为最后一个全加器的进位输出将是True).

  • 哇,谢谢,这正是我想要的!我自己的答案(刚刚回答了我问题的第一部分是:`mapr f(x,state)=(map fst(map f(zip x(replicate(length x)state))),state)麻烦的多了。 (2认同)