3

I'm following this blog about F-algebras It explains that

A terminal coalgebra is usually interpreted in programming as a recipe for generating (possibly infinite) data structures or transition systems.

and says that

A canonical example of a coalgebra is based on a functor whose fixed point is an infinite stream of elements of type e. This is the functor:

data StreamF e a = StreamF e a
  deriving Functor

and this is its fixed point:

data Stream e = Stream e (Stream e)

I’ve tried the code here

the relevant part being

newtype Fix f = Fix (f (Fix f))
unFix :: Fix f -> f (Fix f)
unFix (Fix x) = x

cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg = alg . fmap (cata alg) . unFix

ana :: Functor f => (a -> f a) -> a -> Fix f
ana coalg = Fix . fmap (ana coalg) . coalg

data StreamF e a = StreamF e a
    deriving Functor
data Stream e = Stream e (Stream e)

era :: [Int] -> StreamF Int [Int]
era (p : ns) = StreamF p (filter (notdiv p) ns)
    where notdiv p n = n `mod` p /= 0

primes = ana era [2..]

I’m getting this error

main.hs:42:14: error:
• Can’t make a derived instance of ‘Functor (StreamF e)’:
You need DeriveFunctor to derive an instance for this class
• In the data declaration for ‘StreamF’

Where am I going wrong?

duplode
  • 33,731
  • 7
  • 79
  • 150
  • 1
    You can't use `deriving (Functor)` in vanilla Haskell. You need the pragma `{-# LANGUAGE DeriveFunctor #-}` at the top of your file. More info [here](https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DeriveFunctor). – AJF Dec 29 '17 at 13:43

1 Answers1

3

deriving is very limited in Haskell without using language extensions. Since the compiler can't always work out what a Functor instance should be, deriving Functor is not standard Haskell.

However, there is a language extension that allows this, namely -XDeriveFunctor. To enable this extension do one of:

  • Compile with the flag -XDeriveFunctor. (Eg: run ghc -XDeriveFunctor Main.hs when compiling)

  • Write the pragma {-# LANGUAGE DeriveFunctor #-} at the top of your file.

Here's how your file would look with this pragma added:

{-# LANGUAGE DeriveFunctor #-}

newtype Fix f = Fix (f (Fix f))
unFix :: Fix f -> f (Fix f)
unFix (Fix x) = x

cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg = alg . fmap (cata alg) . unFix

ana :: Functor f => (a -> f a) -> a -> Fix f
ana coalg = Fix . fmap (ana coalg) . coalg

data StreamF e a = StreamF e a
    deriving Functor
data Stream e = Stream e (Stream e)

era :: [Int] -> StreamF Int [Int]
era (p : ns) = StreamF p (filter (notdiv p) ns)
    where notdiv p n = n `mod` p /= 0

primes = ana era [2..]

If you plan on using GHCi, use :set -XDeriveFunctor before loading the file.

AJF
  • 11,767
  • 2
  • 37
  • 64
  • 2
    Rather, the compiler *can* derive a `Functor` instance (it's fairly trivial to do so), it just isn't *required* to do so in Haskell 2010. – chepner Dec 29 '17 at 14:22