Skip to content

Instantly share code, notes, and snippets.

@Icelandjack
Last active January 30, 2017 14:47
Show Gist options
  • Save Icelandjack/d14424e3abb0c957f248c2e3b60b5872 to your computer and use it in GitHub Desktop.
Save Icelandjack/d14424e3abb0c957f248c2e3b60b5872 to your computer and use it in GitHub Desktop.
Deriving for Classes

Just like you can derive instances for data types (example is from homoiconic)

data Foo = F Int Bool 
 deriving Show

maybe it makes sense to do it for certain type classes.

If you define

class Num a where
 (+), (-), (*) :: a -> a -> a
 negate, abs, signum :: a -> a
 fromInteger :: Integer -> a
 
class Num a => Fractional a where
 (/) :: a -> a -> a
 recip :: a -> a
 fromRational :: Rational -> a

the following instances could be define automatically

instance FAlgebra Num where
 data Sig Num a
  = Sig_add a a
  | Sig_mul a a
  | Sig_min a a
  | Sig_neg a
  | Sig_abs a
  | Sig_signum a
  | Sig_fromInteger Integer
  deriving Functor
  
 runSig :: Num a => Sig Num a -> a
 runSig (Sig_add a b)  = a + b
 runSig (Sig_mul a b)  = a * b
 runSig (Sig_min a b)  = a - b
 runSig (Sig_neg a)    = negate a
 runSig (Sig_abs a)    = abs a
 runSig (Sig_signum a) = signum a
 runSig (Sig_fromInteger i) = fromInteger

instance FAlgebra Fractional where
 data Sig Fractional a
  = Sig_div a a
  | Sig_recip a
  | Sig_fromRational Rational
  | Sig_Fractional_Num (Sig Num a)
  deriving Functor
  
 runSig :: Fractional a => Sig Fractional a -> a
 runSig (Sig_div a1 a2)        = a1/a2
 runSig (Sig_recip a)          = recip a
 runSig (Sig_fromRational r)   = fromRational r
 runSig (Sig_Fractional_Num s) = runSig s

for a type class

class Functor (Sig alg) => FAlgebra alg where
 data Sig alg a
 runSig :: alg a => Sig alg a -> a

So my questions are

Are there other (Type -> Constraint) -> Constraint type classes that could be derived.

Could this be automated, like default instances using Generic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment