{-# LANGUAGE FlexibleContexts #-} module TypeMachine.TM.Syntax ((<:>), (<::>), (<.>)) where import Language.Haskell.TH (Name) import TypeMachine.TM import TypeMachine.TM.Liftable import TypeMachine.Type -- | Apply a `TM a` value to a 'TM' computation that expects an `a` -- -- Example: -- -- @ -- 'omit' ["id"] '<:>' 'toType' ''User -- @ (<:>) :: (LiftableTMFunction (a -> b)) => (a -> b) -> TM a -> b <:> :: forall a b. LiftableTMFunction (a -> b) => (a -> b) -> TM a -> b (<:>) = (a -> b) -> TM a -> b forall f a b. (LiftableTMFunction f, f ~ (a -> b)) => (a -> b) -> TM a -> b forall a b. ((a -> b) ~ (a -> b)) => (a -> b) -> TM a -> b applyTM -- | Allows passing a name to a 'TM' function that takes a 'Type' -- -- @ -- f '<::>' ''User == f '<:>' 'toType' ''User -- @ (<::>) :: (LiftableTMFunction (Type -> a)) => (Type -> a) -> Name -> a Type -> a f <::> :: forall a. LiftableTMFunction (Type -> a) => (Type -> a) -> Name -> a <::> Name n = Type -> a f (Type -> a) -> TM Type -> a forall a b. LiftableTMFunction (a -> b) => (a -> b) -> TM a -> b <:> Name -> TM Type toType Name n -- | Apply a `a` value to a 'TM' computation that expects an `a`. -- -- It is just an application operator. It exists so that applications of 'TM' functions is visually homogeneous -- Not using it when `a` is the first parameter can enhance readability. -- -- Examples: -- -- @ -- 'omit' '<.>' ["id"] '<:>' 'toType' ''User -- -- Is equivalent to -- 'omit' ["id"] '<:>' 'toType' ''User -- @ -- -- If the parameters to this function were flipped, using '<.>' can be handy: -- -- @ -- 'flip' 'omit' '<:>' 'toType' ''User '<.>' ["id"] -- -- Instead of having to use parenthesis -- ('flip' 'omit' '<:>' 'toType' ''User) ["id"] -- -- Or the application operator: -- 'flip' 'omit' '<:>' 'toType' ''User $ ["id"] -- @ (<.>) :: (a -> b) -> a -> b a -> b f <.> :: forall a b. (a -> b) -> a -> b <.> a v = a -> b f a v