【问题标题】:Haskell State monadic function using recursion使用递归的 Haskell State monadic 函数
【发布时间】:2014-11-08 23:45:10
【问题描述】:

TL:DR: 有没有办法在不传递参数的情况下执行示例 3

我正在尝试了解 haskell (Control.Monad.State) 中的状态单子。我做了一个极其简单的函数:

示例 1

example :: State Int Int
example = do
    e <- get
    put (e*5)
    return e

这个例子适用于 ghci...

runState example 3
(3,15)

我对其进行了修改,使其能够接受参数......

示例 2

example :: Int -> State Int Int
example n = do
    e <- get
    put (e*n)
    return e

也适用于 ghci...

runState (example 5) 3
(3,15)

我让它递归,计算满足某些条件的计算所需的步数

示例 3

example :: Int -> State Int Int
example n = do
    e <- get

    if (n /= 1)
    then do
        put (succ e)
        example (next n)
    else return  (succ e)

next :: Int -> Int
next n
    | even n    = div n 2
    | otherwise = 3*n+1

ghci

evalState (example 13) 0
10

我的问题是,有没有办法在不显式传递值的情况下执行前面的示例?

【问题讨论】:

    标签: haskell recursion monads state-monad


    【解决方案1】:

    您可以将n 存储在e 旁边的状态中,例如:

    example = do
      (e,n) <- get
      if n /= 1
        then do put (succ e, next n); example
        else return e
    

    使用 State monad 有一些开销,因此您应该将其与替代方案进行比较。

    例如,解决此问题的更 Haskelly 方法是组合列表操作来计算答案,例如:

    collatz :: Int -> [Int]
    collatz n = iterate next n
    
    collatzLength n = length $ takeWhile (/= 1) $ collatz n
    

    【讨论】:

    • 这给了我“无法构造无限类型”错误。我已经在这里使用了一个需要将近 10 秒的列表解决方案:bpaste.net/show/f306ad518779 我正在尝试让 haskell 代码使用与运行不到一秒的 c++11 代码类似的算法:bpaste.net/show/b8c67bd4830f无需传递地图、起始编号和计数 另外我想知道如何使用 state monad。感谢您的回答,我正在努力让它工作,看看你要去哪里。
    • 这是一个完整的工作示例,可帮助您找出类型错误:lpaste.net/113963
    • 您关于如何编写性能与 C++ 代码一样好的 Haskell 例程的问题值得提出一个新的 SO 问题。
    • 这个问题 99% 是关于使用 state monad,我只是使用 collat​​z 序列作为我忘记的词......(使用一些非常愚蠢的东西作为解释和工作示例,而不是一个只会让事情变得更加复杂的现实世界的例子)。我才刚刚开始学习 monad,而且似乎没有很多这种过度简化的例子......其中很多都与随机数和解析器有关。所以非常感谢你现在正在工作的答案。我只是忘记在输入时去掉参数。
    猜你喜欢
    • 2011-02-14
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多