2

I'm trying to create a Cofree structure by anamorphism, according to this post. But the compiler complains about type mismatch:

Expected type: Base (Cofree Term E) (E, Fix Term)
  Actual type: CofreeF Term E (E, Fix Term)

But at the source code of recursion-schemes package, there is an type instance definition:

type instance Base (Cofree f a) = CofreeF f a

How can I make the haskell compiler unify that type with this specific type instance equation successfully?

The code is almost the same as in the link:

import qualified Control.Comonad.Trans.Cofree as COFREEF

type E = Int
type Term = Maybe

annotate :: E -> Fix Term -> COFREEF.Cofree Term E
annotate = curry (ana coalg)
  where
    coalg :: (E, Fix Term) -> COFREEF.CofreeF Term E (E, Fix Term)
    coalg (environment, Fix term) = environment COFREEF.:< fmap ((,) 
environment) term

And the exact error message:

Couldn't match type ‘COFREEF.CofreeF Term E (E, Fix Term)’
                 with ‘Compose
                         Data.Functor.Identity.Identity
                         (COFREEF.CofreeF Maybe Int)
                         (E, Fix Term)’
  Expected type: (E, Fix Term)
                 -> Base (COFREEF.Cofree Term E) (E, Fix Term)
    Actual type: (E, Fix Term)
                 -> COFREEF.CofreeF Term E (E, Fix Term)
• In the first argument of ‘ana’, namely ‘coalg’
  In the first argument of ‘curry’, namely ‘(ana coalg)’
  In the expression: curry (ana coalg)
Jiaming Lu
  • 875
  • 6
  • 20
  • Please include your code in the question, as well as what version of `recursion-schemes` you're using – jberryman Jul 02 '18 at 03:08
  • The code is exactly same as the `annotate` function in the link, with `Term` aliased to `Maybe` and `E` aliased to `Int`, and `calcEnv` function is replaced by `const`. The version of `recursion-schemes` is 5.0.2 – Jiaming Lu Jul 02 '18 at 03:26
  • Huh, it looks to me like the first part of the error (mentioning Compose) is not consistent with the "Expected ... Actual... " part, which seems like a bug but I may be missing something. What ghc version? – jberryman Jul 02 '18 at 04:21
  • GHC version is 8.2.2 – Jiaming Lu Jul 02 '18 at 05:33
  • @jberryman No, GHC is fine. The actual type here corresponds to the very first type in the message, and the expected type the second. That is, the types in the message are ordered "actual expected expected actual." – HTNW Jul 03 '18 at 17:20
  • Oh the trouble is I read `CofreeF` as `Cofree` so it looked like GHC was giving a nonsensical error – jberryman Jul 03 '18 at 17:36

1 Answers1

1

Cofree is just a type synonym

newtype CofreeT f w a = CofreeT { runCofreeT :: w (CofreeF f a (CofreeT f w a)) }
type Cofree f = CofreeT f Identity

and it is CofreeT that has a Base instance:

type instance Base (CofreeT f w a) = Compose w (CofreeF f a)
-- Base (Cofree f a) ~ Base (CofreeT f Identity a) ~ Compose Identity (CofreeF f a)

The equation from the question is morally equivalent, but it's not a good enough approximation.

Wrap your coalgebra in Compose . Identity

annotate :: E -> Fix Term -> Cofree Term E
annotate = curry $ ana $ Compose . Identity . coalg
  where
    coalg :: (E, Fix Term) -> CofreeF Term E (E, Fix Term)
    coalg (environment, Fix term) = environment :< fmap (environment,) term
HTNW
  • 27,182
  • 1
  • 32
  • 60
  • Finally I found out that I should import `CofreeF(..)` from `Control.Comonad.Trans.Cofree` and `Cofree` from `Control.Comonad.Cofree` for `recursion-schemes`... It's a bit wired. – Jiaming Lu Jul 04 '18 at 01:43