{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-warn-orphans -Wno-noncanonical-monoid-instances #-}
module Data.DeriveLiftedInstances (
deriveInstance,
idDeriv, newtypeDeriv, isoDeriv,
recordDeriv, apDeriv, biapDeriv, monoidDeriv, monoidDerivBy,
showDeriv, ShowsPrec(..),
Derivator(..)
) where
import Language.Haskell.TH
import Data.DeriveLiftedInstances.Internal
import Data.Biapplicative
import Data.Bifoldable
import Control.Monad (zipWithM)
import Data.Reflection
apDeriv :: Derivator -> Derivator
apDeriv :: Derivator -> Derivator
apDeriv Derivator
deriv = Derivator {
res :: Q Exp -> Q Exp
res = \Q Exp
e -> [| fmap (\w -> $(Derivator -> Q Exp -> Q Exp
res Derivator
deriv [| w |])) $Q Exp
e |],
cst :: Q Exp -> Q Exp
cst = \Q Exp
e -> [| foldMap (\w -> $(Derivator -> Q Exp -> Q Exp
cst Derivator
deriv [| w |])) $Q Exp
e |],
eff :: Q Exp -> Q Exp
eff = \Q Exp
e -> [| traverse (\w -> $(Derivator -> Q Exp -> Q Exp
eff Derivator
deriv [| w |])) $Q Exp
e |],
op :: Name -> Q Exp -> Q Exp
op = \Name
nm Q Exp
o -> [| pure $(Derivator -> Name -> Q Exp -> Q Exp
op Derivator
deriv Name
nm Q Exp
o) |],
arg :: Type -> Q Exp -> Q Exp
arg = \Type
ty Q Exp
e -> [| pure $(Derivator -> Type -> Q Exp -> Q Exp
arg Derivator
deriv Type
ty Q Exp
e) |],
var :: (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var = \Q Exp -> Q Exp -> Q Exp
fold Q Exp
v ->
[| fmap (\w -> $(Derivator -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var Derivator
deriv Q Exp -> Q Exp -> Q Exp
fold [| w |])) ($(Q Exp -> Q Exp -> Q Exp
fold [| traverse |] [| id |]) $Q Exp
v) |],
inp :: Q Pat -> Q Pat
inp = Q Pat -> Q Pat
forall a. a -> a
id,
ap :: Q Exp -> Q Exp -> Q Exp
ap = \Q Exp
f Q Exp
a -> [| liftA2 (\g b -> $(Derivator -> Q Exp -> Q Exp -> Q Exp
ap Derivator
deriv [| g |] [| b |])) $Q Exp
f $Q Exp
a |]
}
biapDeriv :: Derivator -> Derivator -> Derivator
biapDeriv :: Derivator -> Derivator -> Derivator
biapDeriv Derivator
l Derivator
r = Derivator {
res :: Q Exp -> Q Exp
res = \Q Exp
e -> [| bimap (\w -> $(Derivator -> Q Exp -> Q Exp
res Derivator
l [| w |])) (\w -> $(Derivator -> Q Exp -> Q Exp
res Derivator
r [| w |])) $Q Exp
e |],
cst :: Q Exp -> Q Exp
cst = \Q Exp
e -> [| bifoldMap (\w -> $(Derivator -> Q Exp -> Q Exp
cst Derivator
l [| w |])) (\w -> $(Derivator -> Q Exp -> Q Exp
cst Derivator
r [| w |])) $Q Exp
e |],
eff :: Q Exp -> Q Exp
eff = \Q Exp
e -> [| bitraverse (\w -> $(Derivator -> Q Exp -> Q Exp
eff Derivator
l [| w |])) (\w -> $(Derivator -> Q Exp -> Q Exp
eff Derivator
r [| w |])) $Q Exp
e |],
op :: Name -> Q Exp -> Q Exp
op = \Name
nm Q Exp
o -> [| bipure $(Derivator -> Name -> Q Exp -> Q Exp
op Derivator
l Name
nm Q Exp
o) $(Derivator -> Name -> Q Exp -> Q Exp
op Derivator
r Name
nm Q Exp
o) |],
arg :: Type -> Q Exp -> Q Exp
arg = \Type
ty Q Exp
e -> [| bipure $(Derivator -> Type -> Q Exp -> Q Exp
arg Derivator
l Type
ty Q Exp
e) $(Derivator -> Type -> Q Exp -> Q Exp
arg Derivator
r Type
ty Q Exp
e) |],
var :: (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var = \Q Exp -> Q Exp -> Q Exp
fold Q Exp
v ->
[| bimap (\w -> $(Derivator -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var Derivator
l Q Exp -> Q Exp -> Q Exp
fold [| w |])) (\w -> $(Derivator -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var Derivator
r Q Exp -> Q Exp -> Q Exp
fold [| w |]))
($(Q Exp -> Q Exp -> Q Exp
fold [| traverseBia |] [| id |]) $Q Exp
v) |],
inp :: Q Pat -> Q Pat
inp = Q Pat -> Q Pat
forall a. a -> a
id,
ap :: Q Exp -> Q Exp -> Q Exp
ap = \Q Exp
f Q Exp
a -> [| biliftA2 (\g b -> $(Derivator -> Q Exp -> Q Exp -> Q Exp
ap Derivator
l [| g |] [| b |])) (\g b -> $(Derivator -> Q Exp -> Q Exp -> Q Exp
ap Derivator
r [| g |] [| b |])) $Q Exp
f $Q Exp
a |]
}
monoidDeriv :: Derivator
monoidDeriv :: Derivator
monoidDeriv = Q Exp -> Q Exp -> Derivator
monoidDerivBy [| (<>) |] [| mempty |]
monoidDerivBy :: Q Exp -> Q Exp -> Derivator
monoidDerivBy :: Q Exp -> Q Exp -> Derivator
monoidDerivBy Q Exp
append Q Exp
empty = Derivator
idDeriv {
cst = const [| mempty |],
eff = \Q Exp
e -> [| pure $Q Exp
e |],
op = \Name
_ Q Exp
_ -> Q Exp
empty,
arg = \Type
_ Q Exp
_ -> Q Exp
empty,
var = \Q Exp -> Q Exp -> Q Exp
fold Q Exp
v -> [| ($(Q Exp -> Q Exp -> Q Exp
fold [| foldMapBy $Q Exp
append $Q Exp
empty |] [| id |]) $Q Exp
v) |],
ap = \Q Exp
f Q Exp
a -> [| $Q Exp
append $Q Exp
f $Q Exp
a |]
}
newtypeDeriv :: Name -> Name -> Derivator -> Derivator
newtypeDeriv :: Name -> Name -> Derivator -> Derivator
newtypeDeriv Name
mk Name
un = Q Exp -> Q Exp -> Derivator -> Derivator
isoDeriv (Exp -> Q Exp
forall a. a -> Q a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp -> Q Exp) -> Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Exp
ConE Name
mk) (Exp -> Q Exp
forall a. a -> Q a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp -> Q Exp) -> Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Exp
VarE Name
un)
isoDeriv :: Q Exp -> Q Exp -> Derivator -> Derivator
isoDeriv :: Q Exp -> Q Exp -> Derivator -> Derivator
isoDeriv Q Exp
mk Q Exp
un Derivator
deriv = Derivator
deriv {
res = \Q Exp
v -> [| $Q Exp
mk $(Derivator -> Q Exp -> Q Exp
res Derivator
deriv Q Exp
v) |],
var = \Q Exp -> Q Exp -> Q Exp
fold Q Exp
v -> Derivator -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var Derivator
deriv Q Exp -> Q Exp -> Q Exp
fold [| $(Q Exp -> Q Exp -> Q Exp
fold [| fmap |] Q Exp
un) $Q Exp
v |]
}
recordDeriv :: Q Exp -> [(Q Exp, Derivator)] -> Derivator
recordDeriv :: Q Exp -> [(Q Exp, Derivator)] -> Derivator
recordDeriv Q Exp
mk [(Q Exp, Derivator)]
flds = Derivator {
res :: Q Exp -> Q Exp
res = \Q Exp
vs -> do [Name]
vnms <- Q [Name]
vars; [| case $Q Exp
vs of $([Name] -> Q Pat
pat [Name]
vnms) -> $((Q Exp -> ((Q Exp, Derivator), Name) -> Q Exp)
-> Q Exp -> [((Q Exp, Derivator), Name)] -> Q Exp
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Q Exp
f ((Q Exp
_, Derivator
d), Name
v) -> [| $Q Exp
f $(Derivator -> Q Exp -> Q Exp
res Derivator
d (Name -> Q Exp
ex Name
v)) |]) Q Exp
mk ([(Q Exp, Derivator)] -> [Name] -> [((Q Exp, Derivator), Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(Q Exp, Derivator)]
flds [Name]
vnms)) |],
cst :: Q Exp -> Q Exp
cst = \Q Exp
vs -> do [Name]
vnms <- Q [Name]
vars; [| case $Q Exp
vs of $([Name] -> Q Pat
pat [Name]
vnms) -> $((Q Exp -> ((Q Exp, Derivator), Name) -> Q Exp)
-> Q Exp -> [((Q Exp, Derivator), Name)] -> Q Exp
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Q Exp
f ((Q Exp
_, Derivator
d), Name
v) -> [| $Q Exp
f <> $(Derivator -> Q Exp -> Q Exp
cst Derivator
d (Name -> Q Exp
ex Name
v)) |]) [| mempty |] ([(Q Exp, Derivator)] -> [Name] -> [((Q Exp, Derivator), Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(Q Exp, Derivator)]
flds [Name]
vnms)) |],
eff :: Q Exp -> Q Exp
eff = \Q Exp
vs -> do [Name]
vnms <- Q [Name]
vars; [| case $Q Exp
vs of $([Name] -> Q Pat
pat [Name]
vnms) -> $((Q Exp -> ((Q Exp, Derivator), Name) -> Q Exp)
-> Q Exp -> [((Q Exp, Derivator), Name)] -> Q Exp
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Q Exp
f ((Q Exp
_, Derivator
d), Name
v) -> [| $Q Exp
f <*> $(Derivator -> Q Exp -> Q Exp
eff Derivator
d (Name -> Q Exp
ex Name
v)) |]) [| pure $Q Exp
mk |] ([(Q Exp, Derivator)] -> [Name] -> [((Q Exp, Derivator), Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(Q Exp, Derivator)]
flds [Name]
vnms)) |],
op :: Name -> Q Exp -> Q Exp
op = \Name
nm Q Exp
o -> Q [Exp] -> Q Exp
tup (Q [Exp] -> Q Exp) -> Q [Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ ((Q Exp, Derivator) -> Q Exp) -> [(Q Exp, Derivator)] -> Q [Exp]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (\(Q Exp
_, Derivator
d) -> Derivator -> Name -> Q Exp -> Q Exp
op Derivator
d Name
nm Q Exp
o) [(Q Exp, Derivator)]
flds,
arg :: Type -> Q Exp -> Q Exp
arg = \Type
ty Q Exp
e -> Q [Exp] -> Q Exp
tup (Q [Exp] -> Q Exp) -> Q [Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ ((Q Exp, Derivator) -> Q Exp) -> [(Q Exp, Derivator)] -> Q [Exp]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (\(Q Exp
_, Derivator
d) -> Derivator -> Type -> Q Exp -> Q Exp
arg Derivator
d Type
ty Q Exp
e) [(Q Exp, Derivator)]
flds,
var :: (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var = \Q Exp -> Q Exp -> Q Exp
fold Q Exp
v -> Q [Exp] -> Q Exp
tup (Q [Exp] -> Q Exp) -> Q [Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ ((Q Exp, Derivator) -> Q Exp) -> [(Q Exp, Derivator)] -> Q [Exp]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (\(Q Exp
fld, Derivator
d) -> Derivator -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp -> Q Exp
var Derivator
d Q Exp -> Q Exp -> Q Exp
fold [| $(Q Exp -> Q Exp -> Q Exp
fold [| fmap |] Q Exp
fld) $Q Exp
v |]) [(Q Exp, Derivator)]
flds,
inp :: Q Pat -> Q Pat
inp = Q Pat -> Q Pat
forall a. a -> a
id,
ap :: Q Exp -> Q Exp -> Q Exp
ap = \Q Exp
fs Q Exp
as -> do
[Name]
fnms <- Q [Name]
funs
[Name]
vnms <- Q [Name]
vars
[| case ($Q Exp
fs, $Q Exp
as) of ($([Name] -> Q Pat
pat [Name]
fnms), $([Name] -> Q Pat
pat [Name]
vnms)) -> $(Q [Exp] -> Q Exp
tup (Q [Exp] -> Q Exp) -> Q [Exp] -> Q Exp
forall a b. (a -> b) -> a -> b
$ ((Q Exp, Derivator) -> (Name, Name) -> Q Exp)
-> [(Q Exp, Derivator)] -> [(Name, Name)] -> Q [Exp]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (\(Q Exp
_, Derivator
d) (Name
f, Name
v) -> Derivator -> Q Exp -> Q Exp -> Q Exp
ap Derivator
d (Name -> Q Exp
ex Name
f) (Name -> Q Exp
ex Name
v)) [(Q Exp, Derivator)]
flds ([Name] -> [Name] -> [(Name, Name)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
fnms [Name]
vnms)) |]
}
where
tup :: Q [Exp] -> Q Exp
#if __GLASGOW_HASKELL__ >= 810
tup :: Q [Exp] -> Q Exp
tup = ([Exp] -> Exp) -> Q [Exp] -> Q Exp
forall a b. (a -> b) -> Q a -> Q b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Maybe Exp] -> Exp
TupE ([Maybe Exp] -> Exp) -> ([Exp] -> [Maybe Exp]) -> [Exp] -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> Maybe Exp) -> [Exp] -> [Maybe Exp]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Exp -> Maybe Exp
forall a. a -> Maybe a
Just)
#else
tup = fmap TupE
#endif
pat :: [Name] -> Q Pat
pat :: [Name] -> Q Pat
pat = Pat -> Q Pat
forall a. a -> Q a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Pat -> Q Pat) -> ([Name] -> Pat) -> [Name] -> Q Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Pat] -> Pat
TupP ([Pat] -> Pat) -> ([Name] -> [Pat]) -> [Name] -> Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name -> Pat) -> [Name] -> [Pat]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Name -> Pat
VarP
ex :: Name -> Q Exp
ex :: Name -> Q Exp
ex = Exp -> Q Exp
forall a. a -> Q a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp -> Q Exp) -> (Name -> Exp) -> Name -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp
VarE
vars :: Q [Name]
vars :: Q [Name]
vars = String -> Q [Name]
names String
"a"
funs :: Q [Name]
funs :: Q [Name]
funs = String -> Q [Name]
names String
"f"
names :: String -> Q [Name]
names :: String -> Q [Name]
names String
s = ((Q Exp, Derivator) -> Q Name) -> [(Q Exp, Derivator)] -> Q [Name]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (Q Name -> (Q Exp, Derivator) -> Q Name
forall a b. a -> b -> a
const (String -> Q Name
forall (m :: * -> *). Quote m => String -> m Name
newName String
s)) [(Q Exp, Derivator)]
flds
deriveInstance showDeriv [t| Bounded ShowsPrec |]
deriveInstance showDeriv [t| Num ShowsPrec |]
deriveInstance showDeriv [t| Fractional ShowsPrec |]
deriveInstance showDeriv [t| Floating ShowsPrec |]
deriveInstance showDeriv [t| Semigroup ShowsPrec |]
deriveInstance showDeriv [t| Monoid ShowsPrec |]