我有一个功能
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
s序列,并使用上一步中的状态执行每个步骤?
所以例如步骤如下
第一步产生(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 :(得分:4)
功能,
mapM step [25,10,5,1]
或更一般的
traverse step [25,10,5,1]
在step
的每个列表上运行[25,10,5,1]
。调用
runState (mapM step [25,10,5,1]) 41
运行初始状态设置为41
的函数,返回步骤输出列表和最终状态。
([16,1,0,0],0)
如果要列出状态以及输出,只需修改step
以包含它们。
step n = get >>= \x -> put (x `div` n) >> return ((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))
希望有所帮助