Copyright | (C) 2012-2013 Edward Kmett |
---|---|
License | BSD-style (see the file LICENSE) |
Maintainer | Edward Kmett <ekmett@gmail.com> |
Stability | experimental |
Portability | portable |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This is a Template Haskell module for deriving Applicative
and
Monad
instances for data types.
Documentation
makeBound :: Name -> DecsQ Source #
Use to automatically derive Applicative
and Monad
instances for
your datatype.
Also works for components that are lists or instances of Functor
,
but still does not work for a great deal of other things.
The deriving-compat
package may be used to derive the Show1
and Read1
instances. Note that due to Template Haskell staging restrictions, we must
define these instances within the same TH splice as the Show
and Read
instances. (This is needed for GHC 9.6 and later, where Show
and Read
are quantified superclasses of Show1
and Read1
, respectively.)
{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TemplateHaskell #-} import Bound (Scope, makeBound) import Data.Functor.Classes (Show1, Read1, showsPrec1, readsPrec1) import Data.Deriving (deriveShow1, deriveRead1) data Exp a = V a | App (Exp a) (Exp a) | Lam (Scope () Exp a) | ND [Exp a] | I Int deriving (Functor) makeBound ''Exp concat $ sequence [ deriveShow1 ''Exp , deriveRead1 ''Exp , [d| instance Read a => Read (Exp a) where readsPrec = readsPrec1 instance Show a => Show (Exp a) where showsPrec = showsPrec1 |] ]
and in GHCi
ghci> :set -XDeriveFunctor ghci> :set -XTemplateHaskell ghci> import Bound (Scope, makeBound) ghci> import Data.Functor.Classes (Show1, Read1, showsPrec1, readsPrec1) ghci> import Data.Deriving (deriveShow1, deriveRead1) ghci> :{ ghci| data Exp a = V a | App (Exp a) (Exp a) | Lam (Scope () Exp a) | ND [Exp a] | I Int deriving (Functor) ghci| makeBound ''Exp ghci| fmap concat $ sequence [deriveShow1 ''Exp, deriveRead1 ''Exp, [d| instance Read a => Read (Exp a) where { readsPrec = readsPrec1 }; instance Show a => Show (Exp a) where { showsPrec = showsPrec1 } |]] ghci| :}
The Eq
and Ord
instances can be derived similarly:
import Data.Functor.Classes (Eq1, Ord1, eq1, compare1) import Data.Deriving (deriveEq1, deriveOrd1) fmap concat $ sequence [ deriveEq1 ''Exp , deriveOrd1 ''Exp , [d| instance Eq a => Eq (Exp a) where (==) = eq1 instance Ord a => Ord (Exp a) where compare = compare1 |] ]
or in GHCi:
ghci> import Data.Functor.Classes (Eq1, Ord1, eq1, compare1) ghci> import Data.Deriving (deriveEq1, deriveOrd1) ghci> :{ ghci| fmap concat $ sequence [deriveEq1 ''Exp, deriveOrd1 ''Exp, [d| instance Eq a => Eq (Exp a) where { (==) = eq1 }; instance Ord a => Ord (Exp a) where { compare = compare1 } |]] ghci| :}
We cannot automatically derive Eq
and Ord
using the standard GHC mechanism,
because instances require Exp
to be a Monad
:
instance (Monad f, Eq b, Eq1 f, Eq a) => Eq (Scope b f a) instance (Monad f, Ord b, Ord1 f, Ord a) => Ord (Scope b f a)