Data.Map / Data.IntMap是否存在monad实例?

时间:2011-02-11 19:48:36

标签: haskell

我有一个在IntMap上运行的算法,我觉得最好用强制表达。也就是说,我想说的是:

  • 在地图中查找值X.
  • 如果符合条件,请从地图中删除此值。
  • 循环,直到地图中不再存在值。

这表示为两行递归是相当简单的,但实际算法稍微复杂一些,涉及多次查找和删除,所以我希望能够在do中表达它。符号

是否有一个标准的“州”式单子格,其中州由Data.MapData.IntMap表示,我可以在其中执行以下操作:

do
  insert 5 20
  (ma, mv) <- lookup 4
  case mv of
    Just v -> delete (fromJust ma)
    Nothing -> return ()

老实说,我不确定如何最好地表达这一点......由于lookup它似乎会从某种MaybeT IntMap m堆栈中获益。

我尝试根据Data.IntMap定义自己的状态monad做了一些工作,甚至可以使insertdelete工作,但有点困惑如何处理lookup。大多数情况下,我觉得这可能是某人已经解决的问题,但我无法在Hackage上找到它。

1 个答案:

答案 0 :(得分:22)

您是否有任何特殊原因要避免使用monad变压器?如果您从Hackage获得MaybeT包,您可以实现您想要的:

import Control.Monad
import Control.Monad.Maybe
import Control.Monad.State
import qualified Data.Map as Map

type MapM k v a = MaybeT (State (Map.Map k v)) a

lookupM k = MaybeT $ Map.lookup k `liftM` get
insertM k = modify . Map.insert k
deleteM k = modify $ Map.delete k

runMap m = (flip execState) m . runMaybeT

foo = runMap Map.empty $ do
    insertM 5 20
    v <- lookupM 4
    deleteM v

当lookupM失败时,其余的计算失败。你可以随时输入和转义这些monad,这样你就可以在纯函数接口下隐藏它们,它只是你不应该从主要(和使用不安全的函数)中逃脱的IO monad。

所有你需要记住的是任何返回Maybe类型的状态动作只是提升到MaybeT构造函数中。如果你想做IO改变状态为StateT。