首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将有状态计算应用于列表?

如何将有状态计算应用于列表?
EN

Stack Overflow用户
提问于 2015-10-02 13:54:33
回答 3查看 145关注 0票数 1

让我们想象一下大脑的一个虚拟子集:

+增加计数器

-减少计数器

一个简单的程序:

program = "++++--" -- should evaluate to 2

和一个有状态的评价功能:

代码语言:javascript
复制
eval :: Char -> State Int Char
eval '+' = do x <- get
              put (x + 1)
              return 'I'
eval '-' = do x <- get
              put (x - 1)
              return 'D'

你将如何评价这个项目?(在我看来,这是一种fold,但我无法将头绕过去,而且感觉这不是正确的方法.)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-02 14:13:50

您可以使用来自traverse_Data.Foldable

代码语言:javascript
复制
import Data.Foldable (traverse_)
execState (traverse_ eval "++++--") 0
票数 7
EN

Stack Overflow用户

发布于 2015-10-02 14:13:15

您要寻找的函数是sequence,它具有签名sequence :: Monad m => [m a] -> m [a],在处理State这样的单变量时,它是一个非常常见的模式。

对于您的代码,您希望评估器看起来如下所示:

代码语言:javascript
复制
evalBF :: String -> State Int String
evalBF = sequence . map eval

然后,您将对其进行全面评估,如下所示:

代码语言:javascript
复制
main :: IO ()
main = do
       src <- getLine
       print $ runState (evalBF src) 0
票数 5
EN

Stack Overflow用户

发布于 2015-10-02 15:12:22

一个丑陋的解决方案,但使用折叠,你正确地怀疑是适用的。

代码语言:javascript
复制
import Control.Monad.Trans.State

program = "++++--"

eval :: Char -> State Int Char
eval '+' = do
    x <- get
    put (x + 1)
    return 'I'
eval '-' = do
    x <- get
    put (x - 1)
    return 'D'

evalList :: [Char] -> State Int Char
evalList = foldl (\s c -> (s >> eval c)) (return ' ')

main = putStrLn $ show $ runState (evalList program) 0
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32908792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档