我尝试使用memoization来解决 Project Euler’s Problem 14(涉及Collatz序列的长度),这就是我如何保持以前计算的结果.我有这个函数,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
最佳答案 它是状态monad的内部部分的临时重新实现,因为它创建并执行以模拟状态的方式获取并返回附加参数的函数.
您的代码和State之间的主要区别是:
>您在解决方法中硬编码为某种类型的函数传递状态的逻辑.
State提供了一个函数>> =(bind),它定义了如何组合两个有状态函数,或者如何从另一个调用一个有状态函数(所有monad都需要这样做).
>您硬编码从无状态函数创建有状态函数的过程,该函数获取并返回Int.
State提供了一个函数返回,可用于使任何无状态函数有状态(所有monad都需要这样做).
>您可以对您在州的操作进行硬编码,特别是在Map Int Int中记忆函数.
State向get
,set
和modify
提供了一些函数,它们与>> =一起用于创建以各种方式有状态的函数(这特定于State,而不是一般的monad).
所以是的,你基本上已经定义了一个特定monad的非常非常具体和狭窄的情况!
如果你想正式使它成为一个真正的monad,你可以将类似物定义为>> =并返回,甚至可能实现Monad
类型类,这样你就可以在它们上使用Haskell的组合子和语法糖.