Concise way to conditionally update map in State monad

夙愿已清 提交于 2020-01-07 04:19:15

问题


Below is the code from an answer regarding memoization, showing a memoization function used in the State monad, where the state is updated with the result of the passed function if the key is not already in the map.

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

It doesn't seem like idiomatic Haskell: it feels very imperative, with not really that much going on per line.

Is there a way to do the above, but in a more concise/functional style? I've had a look around the functions available at http://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-State-Lazy.html#v:state, but nothing really seems helpful.


回答1:


I think your code is in functional style, but you can bit simplify it.

myMemo f x = maybe work return =<< gets (Map.lookup x)
  where
    work = do
        y <- f x
        modify $ Map.insert x y
        return y



回答2:


This is alternative that uses mapState, as well as >>= and maybe from https://stackoverflow.com/a/44515364/1319998, that avoids all the do notation

myMemo f x = gets (Map.lookup x) >>= maybe y' return
  where
    y' = mapState (\(y, map) -> (y, Map.insert x y map)) $ f x 



回答3:


This is an alternative that expands on https://stackoverflow.com/a/44515364/1319998, using more >>= that avoids all the do notation

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)



回答4:


This is an alternative that expands on https://stackoverflow.com/a/44515364/1319998, essentially de-sugaring the do-notation

myMemo f x = gets (Map.lookup x) >>= maybe y' return
  where
    y' = f x >>= \y -> modify (Map.insert x y) >> return y


来源:https://stackoverflow.com/questions/44515018/concise-way-to-conditionally-update-map-in-state-monad

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!