项目欧拉14使用州monad

时间:2015-04-13 20:24:23

标签: haskell

我试图通过Project Euler来自学Haskell(再次)。问题14(https://projecteuler.net/problem=14)正在乞求动态编程,而且历史上我一直强烈反对monad(由于反复未能学会使用它们以使生活更轻松而不是更难)所以我&# 39;我试图咬紧牙关并使用State monad来记忆我的代码......它进展不顺利。我想清楚,我已经解决了这个简单/缓慢的问题,此时我正试图学习一些东西(即Project Euler No. 14 Haskell不是我想要的东西)。

到目前为止我的代码是:

collatzMemoCheck :: Int -> State (Map Int Int) Int
collatzMemoCheck n = state $ \s -> maybe (let (a, s') = runState (collatzFast n) s
                                          in (a+1, Map.insert n (a+1) s'))
                                         (\len -> (len, s))
                                         (Map.lookup n s)

collatzFast :: Int -> State (Map Int Int) Int
collatzFast 1 = state $ \_ -> (1, Map.singleton 1 1)
collatzFast n
  | even n    = collatzMemoCheck (n `quot` 2)
  | otherwise = collatzMemoCheck (3 * n + 1)

适用于cabal repl中的个别查询,但对于我的生活,我无法弄清楚如何将重复调用的状态链接到collat​​zFast。我想要像

这样的东西
-- DOES NOT WORK
allCollatzLengths = scanl (>>= collatzFast) (return Map.empty) [1..999999]

但我认为这是内在的。 Bind获取前一个State计算的结果部分并将其传递给下一个调用,但我希望它获取前一个State计算的状态部分并将 it 传递给下一个调用。

有没有正确的方法可以做到这一点,还是我把自己画成角落?如果我不能使用>> =,那么拥有monad是什么意思? ......或者没有意义,因为这是一种愚蠢的做法?帮助

1 个答案:

答案 0 :(得分:6)

你可能喜欢

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

特别是mapM collatzFast :: [Int] -> State (Map Int Int) [Int]