需要MonadPlus(ST a)实例

时间:2011-10-06 22:55:17

标签: haskell types state monad-transformers unification

我正在阅读论文Typed Logical Variables in Haskell,但我没有理解最终实施的细节。特别是第4节中介绍的回溯状态转换器。由于某些原因,我不知道,GHC认为我需要在函数MonadPlus(ST a)的{​​{1}}实例,如下所示:

unify

我不确定问题是什么,以及如何修复它。我的印象是我理解前面的讨论和代码,直到这一点,但显然我错了。如果有人能指出出错的地方 - 我是否需要newtype BackT m a = BT { run :: forall b . (a -> m [b]) -> m [b] } instance (Monad m) => Monad (BackT m) where return a = BT (\k -> k a) BT m >>= f = BT (\k -> m (\a -> run (f a) k)) instance (MonadPlus m) => MonadPlus (BackT m) where mzero = BT (\s -> mzero) f `mplus` g = BT (\s -> (run f) s `mplus` (run g) s) type LP a = BackT (ST a) type LR = STRef type Var s a = LR s (Maybe a) data Atom s = VarA (Var s (Atom s)) | Atom String class Unify b a | a -> b where var :: a -> Maybe (Var b a) unify :: a -> a -> LP s () instance Unify s (Atom s) where var (VarA a) = Just a var _ = Nothing unify (Atom a) (Atom b) | a == b = return () -- type checks unify _ _ = mzero -- requires MonadPlus (ST a) instance 实例? - 这会非常有帮助。

[编辑:澄清] 我应该指出作者似乎声称MonadPlus (ST a)mzero上的某些变体,是适当的功能。我只是不知道适当的功能是什么。我想知道的是我是否应该制作一个mzero实例,或者我没有使用正确的函数,并且误读了一些东西。

2 个答案:

答案 0 :(得分:4)

mzero是类型类MonadPlus的成员。特别是

mzero :: MonadPlus m => m a

用于您的函数unify的monad是LP,实际上BackT已使用ST进行实例化。您还为MonadPlus定义了BackT的实例,这取决于底层monad的这种实例。由于ST没有这样的例子,GHC会嘲笑你。

这是重要的部分:

instance (MonadPlus m) => MonadPlus (BackT m) where 
  mzero             = BT (\s -> mzero)
  f `mplus` g = BT (\s -> (run f) s `mplus` (run g) s)

简单地说:这是MonadPlus BackT m的实例,前提是m也是MonadPlus的实例。由于mST实例化,因此您需要ST的该实例。我想知道如何在没有委托的情况下定义一个合理的MonadPlus实例。我有个主意:

instance MonadPlus (BackT m) where
  mzero = BT (const $ return [])
  mplus (BT f) (BT g) = BT $ \a -> do
    fs <- f a
    gs <- g a
    return $ fs ++ gs

这个实例基本上连接了两个输出列表。我希望它符合您的需求。

答案 1 :(得分:3)

BackT MonadPlus实例可能应使用MonadPlus []实例而不是m,如下所示:

instance (Monad m) => MonadPlus (BackT m) where 
  mzero       = BT (\_ -> return mzero)
  f `mplus` g = BT (\s -> liftM2 mplus (run f s) (run g s))