以下是来自an answer regarding memoization的代码,显示状态monad中使用的memoization函数,如果该键不在映射中,则使用传递函数的结果更新状态。
type MyMemo a b = State (Map.Map a b) b
myMemo :: Ord a => (a -> MyMemo a b) -> a -> MyMemo a b
myMemo f x = do
map <- get
case Map.lookup x map of
Just y -> return y
Nothing -> do
y <- f x
modify $ \map' -> Map.insert x y map'
return y
它看起来不像惯用的Haskell:它感觉非常迫切,并不是每行都有那么多。
有没有办法做到这一点,但更简洁/功能的风格?我已经浏览了http://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-State-Lazy.html#v:state处可用的功能,但似乎没有任何帮助。
答案 0 :(得分:3)
我认为你的代码是功能样式的,但你可以简化它。
myMemo f x = maybe work return =<< gets (Map.lookup x)
where
work = do
y <- f x
modify $ Map.insert x y
return y
答案 1 :(得分:0)
这是使用<h1 class="header-title">@Model.CollectionsManagementViewModels
.First()
.Title
</h1>
以及https://stackoverflow.com/a/44515364/1319998的mapState
和>>=
的替代方法,可以避免所有的注释
maybe
答案 2 :(得分:0)
这是一种在https://stackoverflow.com/a/44515364/1319998上展开的替代方案,使用更多>>=
来避免所有的记号
myMemo :: Ord a => (a -> MyMemo a b) -> a -> MyMemo a b
myMemo f x = gets (Map.lookup x) >>= maybe y' return
where
y' = f x >>= \y -> state $ \map -> (y, Map.insert x y map)
答案 3 :(得分:0)
这是一个可以扩展https://stackoverflow.com/a/44515364/1319998的替代方案,基本上可以解除附加费用
myMemo f x = gets (Map.lookup x) >>= maybe y' return
where
y' = f x >>= \y -> modify (Map.insert x y) >> return y