use*_*956 6

嗯,其实不是不能有MonadFix实例,只是库的类型有点太局限了。如果您定义ContT所有可能的rs,那么不仅MonadFix可能,而且所有实例Monad都不需要底层函子:

newtype ContT m a = ContT { runContT :: forall r. (a -> m r) -> m r }
instance Functor (ContT m) where
  fmap f (ContT k) = ContT (\kb -> k (kb . f))
instance Monad (ContT m) where
  return a = ContT ($a)
  join (ContT kk) = ContT (\ka -> kk (\(ContT k) -> k ka))
instance MonadFix m => MonadFix (ContT m) where
  mfix f = ContT (\ka -> mfixing (\a -> runContT (f a) ka<&>(,a)))
    where mfixing f = fst <$> mfix (\ ~(_,a) -> f a )
Run Code Online (Sandbox Code Playgroud)

  • 多态参数“ContT”也称为“Codensity”。它缺乏定义`callCC`的能力。 (12认同)
  • 这个答案解释了为什么你的 `forall r. (a -&gt; mr) -&gt; mr` `ContT` 不能有 `callCC`。http://stackoverflow.com/a/7180154/414413 (4认同)
  • 好吧,确实我无法用 `Codensity` 的这个定义来定义 `Control.Monad.Cont.callCC`(谢谢你,Ørjan,教我一个新词 :-)),但是如果我们使用类型类看起来像 Scheme 的延续,实例几乎自己写:`class MonadCont m where callCC :: (forall b. (a -&gt; mb) -&gt; mb) -&gt; ma`。我们可以以更一致的方式使用这个实例,即我们不直接在延续中获取值,而是使用我们生成的值运行其余的计算,我们还不知道它的类型(因此是`forall`)。 (3认同)