这个问题使用来自http://hackage.haskell.org/package/recursion-schemes-4.0/docs/Data-Functor-Foldable.html的概念/导入
我正在尝试将其扩展为通过变质使给定的单子线程化。这是我要编译的代码:
class (Monad m, Foldable t) => FoldableM m t where
distM :: Base t (m a) -> m (Base t a)
cataM :: (Base t a -> m a) -> t -> m a
cataM f = join . liftM f . distM . fmap (cataM f) . project
但是由于某种原因,对distM
in的调用cataM
无法弄清楚使用相同的t
.
我得到的错误是:
Expected type: Base t (m a) -> m (Base t a)
Actual type: Base t0 (m a) -> m (Base t0 a)
我在这里使代码变得不那么性感,并且更容易调试:
cataM :: forall a . (Base t a -> m a) -> t -> m a
cataM f t = join d
where
a :: Base t t
a = project t
b :: Base t (m a)
b = fmap (cataM f) a
g :: Base t (m a) -> m (Base t a)
g = distM
c :: m (Base t a)
c = g b
d :: m (m a)
d = liftM f c
的定义g
是导致问题的原因。
编辑:据我了解的问题是,当它调用distM
它时,它只Base t
需要推断类型,所以它无法解决t
。这令人沮丧,因为我知道t
我想使用什么。事实上,我认为如果我可以distM
手动提供类型参数,它将解决问题,但我认为这是不可能的。
这是一个解决方案,但我对此不满意:
class (Monad m, Foldable t) => FoldableM m t where
distM :: t -> Base t (m a) -> m (Base t a)
cataM :: forall a . (Base t a -> m a) -> t -> m a
cataM f = join . liftM f . distM (undefined :: t) . fmap (cataM f) . project
编辑 2:很酷的了解Proxy
(感谢 Antal)。我已经使用 Haskell 多年了,刚刚学到了另一个新东西。我喜欢这种语言。我正在使用的解决方案是:
class (Monad m, Foldable t) => FoldableM m t where
distM :: proxy t -> Base t (m a) -> m (Base t a)
cataM :: forall a . (Base t a -> m a) -> t -> m a
cataM f = join . liftM f . distM (Proxy :: Proxy t) . fmap (cataM f) . project