【问题标题】:How can I numerate list items using State monad in Haskell?如何在 Haskell 中使用 State monad 计算列表项?
【发布时间】:2019-05-29 12:19:29
【问题描述】:

问题:

我正在努力理解

有点难以理解如何使用它,我正在寻找一些示例。

假设我要实现一个函数[()] -> [Int]

numerate :: [()] -> [Int]

我应该将列表的每个元素映射到状态然后折叠它吗?

我该如何使用State

预期行为:

numerate [(), (), (), (), ()]
-- [1, 2, 3, 4, 5] 

谢谢!

【问题讨论】:

  • 您的尝试有什么问题?
  • 对不起。我不清楚你的问题是什么......
  • 我想从 map (_ -> modify(+1)) xs 之类的东西开始,但是...折叠后如何返回列表?

标签: state-monad haskell monads state-monad


【解决方案1】:

我们可以实现一个State 对象来增加状态并返回它,比如:

incState :: State Int Int
incState = modify (1+) >> get

然后我们可以在列表上运行这个State Int Int,比如:

numerate :: (Traversable t) => t a -> t Int
numerate = flip evalState 0 . traverse (const incState)

例如:

Prelude Control.Monad.State> numerate Nothing
Nothing
Prelude Control.Monad.State> numerate (Just 'a')
Just 1
Prelude Control.Monad.State> numerate (Just 0)
Just 1
Prelude Control.Monad.State> numerate [1,4,2,5]
[1,2,3,4]
Prelude Control.Monad.State> numerate [(), (), ()]
[1,2,3]

我们还可以使用其他可遍历的结构,例如 Tree

Prelude Control.Monad.State Data.Tree> numerate (Node 'a' [Node 'b' [], Node 'c' []])
Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []},Node {rootLabel = 3, subForest = []}]}

【讨论】:

  • >> 运算符在modify (1+) >> get 中是否忽略先前的状态?
  • @mkUltra: 不,>> 省略了前一个State s a 的结果(所以是a),但是由于modify (1+)State Int (),所以无论如何都没有结果。
  • 我想知道,是否可以只使用 MonadWriter 来做同样的事情?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-27
  • 2021-08-19
相关资源
最近更新 更多