2017-08-01 66 views
0

我有一个函数链接状态单子

step :: Int -> State Int Int 
step n = get >>= \x -> put (x `div` n) >> return (x `mod` n) 

λ> runState (step 25) 41 
(16,1) 

如何运行的step个序列,与n不同的值,并使用来自最后一步的状态下每一步?

所以示例中的步骤将是如下

一步一个产生(16,1)然后我想用作输入我与n = 10下一步应该产生(6, 2)。第一步添加1,第一步添加16,新建n。

n = 25 gives (16,1) then 
n = 10 gives (6,2) then 
n = 5 gives (1,3) then 
n = 1 gives (0,4) 

我知道在这里使用State可能不正确;但我试图用它来学习。

可能的目标是与状态monad一起实现此功能。

greedy :: Double -> Int 
greedy owed = snd $ foldl go (pennies,0) [25, 10, 5, 1] 
    where 
    pennies      = floor . (*100) $ owed 
    go (remaining,counter) coin = (remaining',counter') 
     where 
     remaining' = remaining `mod` coin 
     counter' = counter + remaining `div` coin 
+0

你说的是不是'一步其他任何1 >>第2步>>第3步? – Cubic

+0

@Cubic,我修改了我的问题。 – matthias

回答

3

功能,

mapM step [25,10,5,1] 

或在每个[25,10,5,1]列表的更一般的

traverse step [25,10,5,1] 

运行step。调用

runState (mapM step [25,10,5,1]) 41 

运行初始状态设置为41的函数,返回步骤输出列表和最终状态。

([16,1,0,0],0) 

如果您想要列出状态和输出,只需修改step以包含它们。

步骤N = GET >> = \ X - >把(X div N)>>返回((X mod N),(X div N))

,或者换一种说法

step n = do 
    x <- get 
    let (r,x') = (x `mod` n,x `div` n) 
    put x' 
    return (r,x') 

结果是,([(16,1),(1,0),(0,0),(0,0)],0),仍然不是你要找的,但更接近。恐怕我不明白你的方程的详细程度,不足以得到你正在寻找的东西,但这应该有助于理清州的一部分,让你专注于数学。

作出上述go功能:

go n = do 
    (r,c) <- get 
    let (r',c') = (r `mod` n, c + (r `div` n)) 
    put (r',c') 
    return (r',c') 

runState (mapM go [25,10,5,1]) (41,0) 

产量,

([(16,1),(6,2),(1,3),(0,4)],(0,4)) 

希望帮助

+0

我似乎无法得到它的工作.. :( – matthias

+0

'runState(mapM步骤[25,10,5,1])41 ==>([16,1,0,0],0)'this是我得到的... – matthias

+0

我的错误,没有测试就回答,对不起,它只返回输出,会后修复 –