有一个问题扩展Data.Functor.Foldable

时间:2013-11-19 15:52:10

标签: haskell recursion-schemes

此问题使用http://hackage.haskell.org/package/recursion-schemes-4.0/docs/Data-Functor-Foldable.html

中的概念/导入

我正在尝试将其扩展为通过一个catamorphism线程给定monad。这是我正在尝试编译的代码:

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中对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)。多年来我一直在Haskelling,刚刚学到了另一件新东西。我喜欢这种语言。我正在使用的解决方案是:

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

1 个答案:

答案 0 :(得分:3)

Base t是一个类型系列,因此GHC无法从t了解Base t。如果不提及distM,就无法让t工作。