{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Observe.Event.DSL
(
SelectorSpec (..),
SelectorConstructorSpec (..),
SelectorField (..),
FieldSpec (..),
FieldConstructorSpec (..),
RecordField (..),
AnyQuote (..),
AnyType,
ExplodedName,
upperCamel,
lowerCamel,
kebab,
NonEmptyString ((:|:)),
nonEmptyToString,
)
where
import Control.Applicative
import Data.Char
import Data.List
import Data.List.NonEmpty hiding (fromList, toList)
import Data.String
import GHC.Exts
import Language.Haskell.TH
import Language.Haskell.TH.Syntax.Compat as THC
import Observe.Event.Syntax
data SelectorSpec
= SelectorSpec
!ExplodedName
![SelectorConstructorSpec]
data SelectorConstructorSpec
= SelectorConstructorSpec
!ExplodedName
!SelectorField
data SelectorField
=
Specified !FieldSpec
|
SimpleType !AnyType
|
Inject !Name
|
NoFields
data FieldSpec
= FieldSpec
!ExplodedName
![FieldConstructorSpec]
data FieldConstructorSpec
= FieldConstructorSpec
!ExplodedName
!(NonEmpty AnyType)
instance (a ~ ExplodedName) => RecordField a SelectorField SelectorConstructorSpec where
≔ :: a -> SelectorField -> SelectorConstructorSpec
(≔) = ExplodedName -> SelectorField -> SelectorConstructorSpec
SelectorConstructorSpec
instance (a ~ ExplodedName) => RecordField a FieldSpec SelectorConstructorSpec where
a
k ≔ :: a -> FieldSpec -> SelectorConstructorSpec
≔ FieldSpec
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ FieldSpec -> SelectorField
Specified FieldSpec
v
instance (a ~ ExplodedName, m ~ AnyQuote) => RecordField a (m Type) SelectorConstructorSpec where
a
k ≔ :: a -> m Type -> SelectorConstructorSpec
≔ m Type
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ AnyType -> SelectorField
SimpleType m Type
v
instance (a ~ ExplodedName) => RecordField a Name SelectorConstructorSpec where
a
k ≔ :: a -> Name -> SelectorConstructorSpec
≔ Name
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Name -> Type
ConT Name
v)
instance (a ~ ExplodedName, m ~ AnyQuote) => RecordField a (NonEmpty (m Type)) FieldConstructorSpec where
≔ :: a -> NonEmpty (m Type) -> FieldConstructorSpec
(≔) = ExplodedName -> NonEmpty AnyType -> FieldConstructorSpec
FieldConstructorSpec
instance (a ~ ExplodedName, m ~ AnyQuote) => RecordField a (m Type) FieldConstructorSpec where
a
k ≔ :: a -> m Type -> FieldConstructorSpec
≔ m Type
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ (m Type
v forall a. a -> [a] -> NonEmpty a
:| [])
instance (a ~ ExplodedName) => RecordField a [Name] FieldConstructorSpec where
a
k ≔ :: a -> [Name] -> FieldConstructorSpec
≔ [Name]
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Type
ConT forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall l. IsList l => [Item l] -> l
fromList @(NonEmpty _) [Name]
v)
instance (a ~ ExplodedName) => RecordField a Name FieldConstructorSpec where
a
k ≔ :: a -> Name -> FieldConstructorSpec
≔ Name
v = a
k forall k v a. RecordField k v a => k -> v -> a
≔ ((forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Name -> Type
ConT Name
v) forall a. a -> [a] -> NonEmpty a
:| [])
newtype AnyQuote a = AnyQuote (forall m. THC.Quote m => m a) deriving (forall a b. a -> AnyQuote b -> AnyQuote a
forall a b. (a -> b) -> AnyQuote a -> AnyQuote b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> AnyQuote b -> AnyQuote a
$c<$ :: forall a b. a -> AnyQuote b -> AnyQuote a
fmap :: forall a b. (a -> b) -> AnyQuote a -> AnyQuote b
$cfmap :: forall a b. (a -> b) -> AnyQuote a -> AnyQuote b
Functor)
type AnyType = AnyQuote Type
instance Applicative AnyQuote where
pure :: forall a. a -> AnyQuote a
pure a
x = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x
(AnyQuote forall (m :: * -> *). Quote m => m (a -> b)
f) <*> :: forall a b. AnyQuote (a -> b) -> AnyQuote a -> AnyQuote b
<*> (AnyQuote forall (m :: * -> *). Quote m => m a
x) = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => m (a -> b)
f forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *). Quote m => m a
x
liftA2 :: forall a b c.
(a -> b -> c) -> AnyQuote a -> AnyQuote b -> AnyQuote c
liftA2 a -> b -> c
f (AnyQuote forall (m :: * -> *). Quote m => m a
x) (AnyQuote forall (m :: * -> *). Quote m => m b
y) = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> b -> c
f forall (m :: * -> *). Quote m => m a
x forall (m :: * -> *). Quote m => m b
y
(AnyQuote forall (m :: * -> *). Quote m => m a
x) *> :: forall a b. AnyQuote a -> AnyQuote b -> AnyQuote b
*> (AnyQuote forall (m :: * -> *). Quote m => m b
y) = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => m a
x forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *). Quote m => m b
y
(AnyQuote forall (m :: * -> *). Quote m => m a
x) <* :: forall a b. AnyQuote a -> AnyQuote b -> AnyQuote a
<* (AnyQuote forall (m :: * -> *). Quote m => m b
y) = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => m a
x forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall (m :: * -> *). Quote m => m b
y
instance Monad AnyQuote where
(AnyQuote forall (m :: * -> *). Quote m => m a
x) >>= :: forall a b. AnyQuote a -> (a -> AnyQuote b) -> AnyQuote b
>>= a -> AnyQuote b
f = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ do
a
x' <- forall (m :: * -> *). Quote m => m a
x
let AnyQuote forall (m :: * -> *). Quote m => m b
res = a -> AnyQuote b
f a
x'
forall (m :: * -> *). Quote m => m b
res
instance THC.Quote AnyQuote where
newName :: String -> AnyQuote Name
newName String
s = forall a. (forall (m :: * -> *). Quote m => m a) -> AnyQuote a
AnyQuote forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => String -> m Name
THC.newName String
s
newtype ExplodedName = ExplodedName (NonEmpty NonEmptyString)
instance IsList ExplodedName where
type Item ExplodedName = NonEmptyString
fromList :: [Item ExplodedName] -> ExplodedName
fromList = coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l. IsList l => [Item l] -> l
fromList @(NonEmpty _)
toList :: ExplodedName -> [Item ExplodedName]
toList = forall l. IsList l => l -> [Item l]
toList @(NonEmpty _) forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce
instance IsString ExplodedName where
fromString :: String -> ExplodedName
fromString = forall l. IsList l => [Item l] -> l
fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. a -> [a] -> [a]
: []) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => String -> a
fromString
upperCamel :: (IsList a, Item a ~ NonEmptyString) => a -> String
upperCamel :: forall a. (IsList a, Item a ~ NonEmptyString) => a -> String
upperCamel = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Char
hd :|: String
tl) -> Char -> Char
toUpper Char
hd forall a. a -> [a] -> [a]
: String
tl) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l. IsList l => l -> [Item l]
toList
lowerCamel :: ExplodedName -> String
lowerCamel :: ExplodedName -> String
lowerCamel (ExplodedName ((Char
hd :|: String
tl) :| [NonEmptyString]
rest)) =
(Char -> Char
toLower Char
hd forall a. a -> [a] -> [a]
: String
tl)
forall a. Semigroup a => a -> a -> a
<> forall a. (IsList a, Item a ~ NonEmptyString) => a -> String
upperCamel [NonEmptyString]
rest
kebab :: ExplodedName -> String
kebab :: ExplodedName -> String
kebab = forall a. [a] -> [[a]] -> [a]
intercalate String
"-" forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Char
hd :|: String
tl) -> Char -> Char
toLower Char
hd forall a. a -> [a] -> [a]
: String
tl) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l. IsList l => l -> [Item l]
toList
newtype NonEmptyString = NonEmptyString (NonEmpty Char)
instance IsList NonEmptyString where
type Item NonEmptyString = Char
fromList :: [Item NonEmptyString] -> NonEmptyString
fromList = coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l. IsList l => [Item l] -> l
fromList @(NonEmpty _)
toList :: NonEmptyString -> [Item NonEmptyString]
toList = forall l. IsList l => l -> [Item l]
toList @(NonEmpty _) forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce
{-# COMPLETE (:|:) #-}
pattern (:|:) :: Char -> String -> NonEmptyString
pattern $m:|: :: forall {r}.
NonEmptyString -> (Char -> String -> r) -> ((# #) -> r) -> r
(:|:) hd tl <- NonEmptyString (hd :| tl)
instance IsString NonEmptyString where
fromString :: String -> NonEmptyString
fromString = forall l. IsList l => [Item l] -> l
fromList
nonEmptyToString :: NonEmptyString -> String
nonEmptyToString :: NonEmptyString -> String
nonEmptyToString = forall l. IsList l => l -> [Item l]
toList