{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module Avail.Derive
(
avail, avail'
,
with1, with2, with3, with4, with5, withN,
with1', with2', with3', with4', with5', withN'
,
M (UnsafeLift)
) where
import Avail.Internal
import Language.Haskell.TH hiding (Type)
import qualified Language.Haskell.TH as TH
avail :: Q TH.Type -> Q [Dec]
avail :: Q Type -> Q [Dec]
avail = [Q Type] -> Q Type -> Q [Dec]
avail' []
avail' :: [Q TH.Type] -> Q TH.Type -> Q [Dec]
avail' :: [Q Type] -> Q Type -> Q [Dec]
avail' = (Q Type -> Q Type) -> [Q Type] -> Q Type -> Q [Dec]
avail'' ((Q Type -> Q Type) -> [Q Type] -> Q Type -> Q [Dec])
-> (Q Type -> Q Type) -> [Q Type] -> Q Type -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ \Q Type
m -> [t| M $m |]
avail'' :: (Q TH.Type -> Q TH.Type) -> [Q TH.Type] -> Q TH.Type -> Q [Dec]
avail'' :: (Q Type -> Q Type) -> [Q Type] -> Q Type -> Q [Dec]
avail'' Q Type -> Q Type
mm [Q Type]
pre Q Type
cls = do
Name
mName <- String -> Q Name
newName String
"m"
let m :: Q Type
m = Type -> Q Type
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Type -> Q Type) -> Type -> Q Type
forall a b. (a -> b) -> a -> b
$ Name -> Type
VarT Name
mName
[d|
instance IsEff $cls where
type Superclasses $cls = $(makeList <$> sequence pre)
deriving newtype instance ($cls $m, Eff $cls) => $cls $(mm m) |]
where
makeList :: [Type] -> Type
makeList [] = Type
PromotedNilT
makeList (Type
x : [Type]
xs) = Type
PromotedConsT Type -> Type -> Type
`AppT` Type
x Type -> Type -> Type
`AppT` [Type] -> Type
makeList [Type]
xs
with1 :: (Q TH.Type -> Q a) -> Q a
with1 :: (Q Type -> Q a) -> Q a
with1 = String -> (Q Type -> Q a) -> Q a
forall a. String -> (Q Type -> Q a) -> Q a
with1' String
"a"
with1' :: String -> (Q TH.Type -> Q a) -> Q a
with1' :: String -> (Q Type -> Q a) -> Q a
with1' String
n Q Type -> Q a
f = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' [String
n] (\[Q Type
a] -> Q Type -> Q a
f Q Type
a)
with2 :: (Q TH.Type -> Q TH.Type -> Q a) -> Q a
with2 :: (Q Type -> Q Type -> Q a) -> Q a
with2 = String -> String -> (Q Type -> Q Type -> Q a) -> Q a
forall a. String -> String -> (Q Type -> Q Type -> Q a) -> Q a
with2' String
"a" String
"b"
with2' :: String -> String -> (Q TH.Type -> Q TH.Type -> Q a) -> Q a
with2' :: String -> String -> (Q Type -> Q Type -> Q a) -> Q a
with2' String
n1 String
n2 Q Type -> Q Type -> Q a
f = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' [String
n1, String
n2] (\[Q Type
a, Q Type
b] -> Q Type -> Q Type -> Q a
f Q Type
a Q Type
b)
with3 :: (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with3 :: (Q Type -> Q Type -> Q Type -> Q a) -> Q a
with3 = String
-> String -> String -> (Q Type -> Q Type -> Q Type -> Q a) -> Q a
forall a.
String
-> String -> String -> (Q Type -> Q Type -> Q Type -> Q a) -> Q a
with3' String
"a" String
"b" String
"c"
with3' :: String -> String -> String -> (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with3' :: String
-> String -> String -> (Q Type -> Q Type -> Q Type -> Q a) -> Q a
with3' String
n1 String
n2 String
n3 Q Type -> Q Type -> Q Type -> Q a
f = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' [String
n1, String
n2, String
n3] (\[Q Type
a, Q Type
b, Q Type
c] -> Q Type -> Q Type -> Q Type -> Q a
f Q Type
a Q Type
b Q Type
c)
with4 :: (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with4 :: (Q Type -> Q Type -> Q Type -> Q Type -> Q a) -> Q a
with4 = String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
forall a.
String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
with4' String
"a" String
"b" String
"c" String
"d"
with4' :: String -> String -> String -> String -> (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with4' :: String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
with4' String
n1 String
n2 String
n3 String
n4 Q Type -> Q Type -> Q Type -> Q Type -> Q a
f = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' [String
n1, String
n2, String
n3, String
n4] (\[Q Type
a, Q Type
b, Q Type
c, Q Type
d] -> Q Type -> Q Type -> Q Type -> Q Type -> Q a
f Q Type
a Q Type
b Q Type
c Q Type
d)
with5 :: (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with5 :: (Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a) -> Q a
with5 = String
-> String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
forall a.
String
-> String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
with5' String
"a" String
"b" String
"c" String
"d" String
"e"
with5' :: String -> String -> String -> String -> String -> (Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q TH.Type -> Q a) -> Q a
with5' :: String
-> String
-> String
-> String
-> String
-> (Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a)
-> Q a
with5' String
n1 String
n2 String
n3 String
n4 String
n5 Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a
f = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' [String
n1, String
n2, String
n3, String
n4, String
n5] (\[Q Type
a, Q Type
b, Q Type
c, Q Type
d, Q Type
e] -> Q Type -> Q Type -> Q Type -> Q Type -> Q Type -> Q a
f Q Type
a Q Type
b Q Type
c Q Type
d Q Type
e)
withN :: Int -> ([Q TH.Type] -> Q a) -> Q a
withN :: Int -> ([Q Type] -> Q a) -> Q a
withN Int
n = [String] -> ([Q Type] -> Q a) -> Q a
forall a. [String] -> ([Q Type] -> Q a) -> Q a
withN' ([String] -> ([Q Type] -> Q a) -> Q a)
-> [String] -> ([Q Type] -> Q a) -> Q a
forall a b. (a -> b) -> a -> b
$ (Char
'a' Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> String) -> [Int] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
1..Int
n]
withN' :: [String] -> ([Q TH.Type] -> Q a) -> Q a
withN' :: [String] -> ([Q Type] -> Q a) -> Q a
withN' [String]
n [Q Type] -> Q a
f = do
[Type]
as <- (String -> Q Type) -> [String] -> Q [Type]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Name -> Type) -> Q Name -> Q Type
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Name -> Type
VarT (Q Name -> Q Type) -> (String -> Q Name) -> String -> Q Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Q Name
newName) [String]
n
[Q Type] -> Q a
f (Type -> Q Type
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Type -> Q Type) -> [Type] -> [Q Type]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Type]
as)