Mas*_*eey 2 haskell higher-order-functions
我刚学会了创建高阶函数,并且我想创建一个map函数,该函数能够更改应用于元组的函数,以使该函数应用于该类型的列表.(就像map函数一样.)我试图以这样的方式创建它:它有这个签名:
statefulMap :: ((a,state) -> (b,state)) -> (([a],state) -> ([b],state))
Run Code Online (Sandbox Code Playgroud)
我希望能够使用此函数创建一系列完整加法器,但是如何创建此函数呢?
这实际上已经存在:我们可以使用状态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指定我们"返回"的内容(这里是特定全加器的输出True或False输出).
现在我们可以创建一个有状态的地图,其中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).