This actually already exists: we can use a state monad and use the monadic version of map: mapM.
For instance we can write a function for a full adder. Here I think with state you mean the carry that the previous full adder has generated.
So we can make a full adder as:
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)
The type means that we make a function that alters state. The first Bool specifies the type of the state itself (here a boolean, the carry that is True or False), the second Bool specifies what we "return" (here a True or False as output for the specific full adder).
Now we can make a stateful map, with mapM:
fullAdders :: [(Bool, Bool)] -> State Bool [Bool]
fullAdders = mapM fa
This thus takes a list of 2-tuples (the inputs for every full adder), and produces a State Bool [Bool], so the state is still a Bool, but the result now is a list of booleans [Bool]: a list that contains the output for every full adder.
We can now call it with fullAdders [(True, True), (True, False), (False, False), (True, True)] but this will not give us a list of booleans, but a State Bool [Bool]. We can the "run" the state monad by specifying the initial state. We can do this by using runState :: State a b -> a -> (a, b), so we can call it with:
runState (fullAdders [(True, True), (True, False), (False, False), (True, True)]) False
this produces:
Prelude Control.Monad.State.Lazy> runState (fullAdders [(True, True), (True, False), (False, False), (True, True)]) False
([False,False,True,False],True)
so a 2-tuple with as first item the result, and as second item the new state (here True, since the carry output of the last full adder will be True).
mapwhich has the type(a -> b) -> [a] -> [b]. Note thatmaptakes two parameters. - Code-ApprenticemapMwith a state monad for instance. - Willem Van OnsemmapAccumLand variants. - chi->operator works right-to-left. - Willem Van Onsem