Haskell使用递归的状态monadic函数

时间:2014-11-08 23:45:11

标签: haskell recursion monads state-monad

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

我试图理解haskell中的状态monad(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

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

1 个答案:

答案 0 :(得分:3)

您可以将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