yong
yong

Reputation: 3633

GHC.Generics example doesn't work

I'm trying to get the example implementation of a generic binary encoding class described in GHC.Generics to work, but when I try to compile it the following code I get an error.

import GHC.Generics

class Encode' f where
  encode' :: f p -> [Bool]

instance Encode' V1 where
  encode' x = undefined

instance Encode' U1 where
  encode' U1 = []

instance (Encode' f, Encode' g) => Encode' (f :+: g) where
  encode' (L1 x) = False : encode' x
  encode' (R1 x) = True  : encode' x

instance (Encode' f, Encode' g) => Encode' (f :*: g) where
  encode' (x :*: y) = encode' x ++ encode' y

instance (Encode c) => Encode' (K1 i c) where
  encode' (K1 x) = encode x

instance (Encode' f) => Encode' (M1 i t f) where
  encode' (M1 x) = encode' x

class Encode a where
  encode :: a -> [Bool]
  default encode :: (Generic a) => a -> [Bool]
  encode x = encode' (from x)

GHC complains with:

Could not deduce (Encode' (Rep a)) arising from a use of ‘encode'’
from the context (Encode a)
  bound by the class declaration for ‘Encode’
  ...
or from (Generic a)
  bound by the type signature for encode :: Generic a => a -> [Bool]
  ...
In the expression: encode' (from x)
In an equation for ‘encode’: encode x = encode' (from x)

What am I missing?

Upvotes: 3

Views: 163

Answers (1)

Cirdec
Cirdec

Reputation: 24156

Not everything that is Generic can be encoded by encode'. Only those things that are both Generic and have a representation, Rep a that has an Encode' instance can be encoded by the generic encode'. The compiler doesn't know (and can't know) that there isn't something Generic whose Rep isn't covered by an Encode' instance. An author of a Generic instance could use a type for their Rep that doesn't even exist yet.

You need to add the requested Encode' (Rep a) constraint to the context for the default encode.

default encode :: (Generic a, Encode' (Rep a)) => a -> [Bool]

Upvotes: 5

Related Questions