在Haskell中实现memoization是monad吗?

时间:2015-12-01 21:08:48

标签: haskell monads memoization

我尝试使用memoization来解决Project Euler's Problem 14(涉及Collat​​z序列的长度),这就是我如何保持以前计算的结果。我有这个函数,collatzSequence,我想要记住,我用computeWithMemo记忆它,它接受一个函数,一个值来计算函数,Map,然后返回此时函数的值和更新的Map。这是Monad模式吗?谢谢!

import Data.Map                                                                   

computeWithMemo :: (Int -> Int) -> Int -> Map Int Int -> (Maybe Int, (Map Int Int)
computeWithMemo fun key memo                                                      
  | elem key (Data.Map.keys memo) = (Data.Map.lookup key memo, memo)              
  | otherwise = (Just (fun key), Data.Map.insert key (fun key) memo)              

collatzSequence :: Int -> Int                                                     
collatzSequence x                                                                 
  | x == 1 = 1                                                                    
  | even x = 1 + collatzSequence (x `div` 2)                                      
  | odd x = 1 + collatzSequence (x*3 + 1)                                         

memoize f = computeWithMemo f                                                     

memoizedCollatz = memoize collatzSequence                                         

solve x m                                                                         
  | x > 1 = solve (x-1) (snd (computeWithMemo (collatzSequence) x m))             
  | otherwise = m                                                                 

solution = solve 10000 Data.Map.empty                                             

1 个答案:

答案 0 :(得分:1)

它是State monad内部部分的临时重新实现,因为它创建并执行以模拟状态的方式获取并返回其他参数的函数。

您的代码与State之间的主要区别是:

  • 您在solve方法中为某种类型的函数传递状态的逻辑硬编码。

    State提供了一个函数>>=(bind),它定义了如何组合两个有状态函数,或者如何从另一个调用一个有状态函数(所有monad都需要这样做)。

  • 您需要对无状态函数创建有状态函数的过程进行硬编码,该函数采用并返回Int

    State提供了一个函数return,可以用来使任何无状态函数有状态(所有monad都需要这样做)。

  • 您可以对您在州的操作进行硬编码,特别是在Map Int Int中记忆功能。

    Stategetsetmodify提供了一些功能,与>>=一起可用于创建各种状态的函数方式(这是State特有的,而不是一般的monad)。

所以是的,你基本上已经定义了一个特定monad的非常非常具体和狭窄的案例!

如果你想正式使它成为一个真正的monad,你可以将类似物定义为>>=return,甚至可以实现Monad类型类,这样你就可以使用Haskell的组合子和句法糖在他们身上。