Haskell Monad状态示例 [英] Haskell Monad State Example
问题描述
我正在尝试Haskell的Control.Monad.State
,它尝试遍历字符串或整数列表,对它们进行计数,然后用整数0
替换字符串条目.我已经完成了计数工作,但是创建替换列表失败.这是我的代码
可以在屏幕上正确打印[3,6]
.如何使其创建所需的列表[6,0,3,8,0,2,9,1,0]
?
I'm experimenting with Haskell's Control.Monad.State
by trying to iterate through a list of either strings or integers, counting them, and replacing string entries with the integer 0
. I have managed to do the counting part, but failed in creating the replaced list. Here is my code
which correctly prints [3,6]
to the screen. How can I make it create the desired list [6,0,3,8,0,2,9,1,0]
?
module Main( main ) where
import Control.Monad.State
l = [
Right 6,
Left "AAA",
Right 3,
Right 8,
Left "CCC",
Right 2,
Right 9,
Right 1,
Left "D"]
scanList :: [ Either String Int ] -> State (Int,Int) [ Int ]
scanList [ ] = do
(ns,ni) <- get
return (ns:[ni])
scanList (x:xs) = do
(ns,ni) <- get
case x of
Left _ -> put (ns+1,ni)
Right _ -> put (ns,ni+1)
case x of
Left _ -> scanList xs -- [0] ++ scanList xs not working ...
Right i -> scanList xs -- [i] ++ scanList xs not working ...
startState = (0,0)
main = do
print $ evalState (scanList l) startState
推荐答案
[0] ++ scanList xs
不起作用,因为scanList xs
不是列表,而是State (Int,Int) [Int]
.要解决此问题,您将需要使用fmap
/<$>
.
[0] ++ scanList xs
doesn't work because scanList xs
is not a list, but a State (Int,Int) [Int]
. To fix that, you will need to use fmap
/<$>
.
您还需要更改基本大小写,以不使状态值成为返回值.
You will also need to change the base case to not make the state value be the return value.
scanList :: [Either String Int] -> State (Int, Int) [Int]
scanList [] = return []
scanList (x:xs) = do
(ns,ni) <- get
case x of
Left _ -> put (ns+1, ni)
Right _ -> put (ns, ni+1)
case x of
Left _ -> (0 :) <$> scanList xs
Right i -> (i :) <$> scanList xs
但是,为了进一步简化代码,最好使用mapM
/traverse
和state
删除大部分递归和get
/put
语法的样板.
To further simplify the code, however, it would be good to use mapM
/traverse
and state
to remove most of the boilerplate of the recursion and get
/put
syntax.
scanList :: [Either String Int] -> State (Int, Int) [Int]
scanList = mapM $ \x -> state $ \(ns, ni) -> case x of
Left _ -> (0, (ns+1, ni))
Right i -> (i, (ns, ni+1))
这篇关于Haskell Monad状态示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!