module Ermine.Syntax
(
Variable(_Var)
, App(_App)
, apps
, ( ## )
, AppHash(_AppHash)
, appHashes
, AppDict(_AppDict)
, appDicts
, Fun(_Fun)
, (~>)
, Tup(_Tup)
, tup
, tup'
) where
import Bound
import Bound.Var
import Control.Lens
import Data.Tagged
import Ermine.Syntax.Scope
class Variable t where
_Var :: Prism' (t a) a
instance Variable Maybe where
_Var = _Just
instance Variable [] where
_Var = prism return $ \xs -> case xs of
[x] -> Right x
_ -> Left xs
instance Variable (Either b) where
_Var = _Right
instance Variable m => Variable (Scope b m) where
_Var = _Scope._Var._F._Var
class App t where
_App :: Prism' (t a) (t a, t a)
instance (Variable t, App t) => App (Scope b t) where
_App = prism (\ (Scope x, Scope y) -> Scope $ x ## y) $ \t@(Scope b) -> case b^?_App of
Just (x,y) -> Right (Scope x, Scope y)
_ -> case b^?_Var of
Just (F xy) -> case xy^?_App of
Just (x,y) -> Right (Scope (_Var # F x), Scope (_Var # F y))
_ -> Left t
_ -> Left t
infixl 9 ##
(##) :: App t => t a -> t a -> t a
(##) = curry (review _App)
apps :: App t => t a -> [t a] -> t a
apps = foldl (##)
class AppHash t where
_AppHash :: Prism' (t a) (t a, t a)
instance (Variable t, AppHash t) => AppHash (Scope b t) where
_AppHash = prism (\ (Scope x, Scope y) -> Scope $ _AppHash # (x,y)) $ \t@(Scope b) -> case b^?_AppHash of
Just (x,y) -> Right (Scope x, Scope y)
_ -> case b^?_Var of
Just (F xy) -> case xy^?_AppHash of
Just (x,y) -> Right (Scope (_Var # F x), Scope (_Var # F y))
_ -> Left t
_ -> Left t
appHashes :: AppHash t => t a -> [t a] -> t a
appHashes = foldl $ curry $ review _AppHash
class AppDict c where
_AppDict :: Prism' (c a) (c a, c a)
instance (Variable t, AppDict t) => AppDict (Scope b t) where
_AppDict = prism (\ (Scope x, Scope y) -> Scope $ _AppDict # (x,y)) $ \t@(Scope b) -> case b^?_AppDict of
Just (x,y) -> Right (Scope x, Scope y)
_ -> case b^?_Var of
Just (F xy) -> case xy^?_AppDict of
Just (x,y) -> Right (Scope (_Var # F x), Scope (_Var # F y))
_ -> Left t
_ -> Left t
appDicts :: AppDict t => t a -> [t a] -> t a
appDicts = Prelude.foldl $ curry $ review _AppDict
class Fun t where
_Fun :: Prism' (t a) (t a, t a)
infixr 0 ~>
(~>) :: Fun t => t a -> t a -> t a
(~>) = curry (review _Fun)
class (Reviewable p, Functor f) => Tup p f t where
_Tup :: Optic' p f t [t]
tup :: Tup Tagged Identity t => [t] -> t
tup = review _Tup
tup' :: Tup Tagged Identity t => [t] -> t
tup' [x] = x
tup' xs = review _Tup xs