Возникла проблема с расширением Data.Functor.Foldable

В этом вопросе используются понятия / импорт из 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 в 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 (спасибо, Антал). Я был на Хаскеллинге уже много лет и только что узнал еще одну новую вещь. Я люблю этот язык. Я использую решение:

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 ответ

Решение

Base t это типовая семья, поэтому GHC не может знать t от Base t, Там нет способа получить distM работать без упоминания t,

Другие вопросы по тегам