我正在阅读论文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
实例,或者我没有使用正确的函数,并且误读了一些东西。
答案 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
的实例。由于m
与ST
实例化,因此您需要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))