Annotations-0.2.1: tests/MultiRec/Expr.hs
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE Rank2Types #-}
module MultiRec.Expr where
import Annotations.MultiRec.ShowFam
import Annotations.MultiRec.ErrorAlg
import Generics.MultiRec.Base
data Expr
= EAdd Expr Expr
| EMul Expr Expr
| ETup Expr Expr
| EIntLit Int
| ETyped Expr Type
deriving (Eq, Show)
data Type
= TyInt
| TyTup Type Type
deriving (Eq, Show)
type PF_Expr =
I Expr :*: I Expr :*: U
:+: I Expr :*: I Expr :*: U
:+: I Expr :*: I Expr :*: U
:+: K Int :*: U
:+: I Expr :*: I Type :*: U
type PF_Type =
U
:+: I Type :*: I Type :*: U
type instance PF Tuples = PF_Expr :>: Expr :+: PF_Type :>: Type
data Tuples :: * -> * where
Expr :: Tuples Expr
Type :: Tuples Type
instance EqS Tuples where
eqS Expr Expr = Just Refl
eqS Type Type = Just Refl
eqS _ _ = Nothing
instance El Tuples Expr where
proof = Expr
instance El Tuples Type where
proof = Type
instance ShowFam Tuples where
showFam Expr = show
showFam Type = show
instance Fam Tuples where
from Expr ex = L . Tag $ case ex of
EAdd x y -> L $ I (I0 x) :*: I (I0 y) :*: U
EMul x y -> R . L $ I (I0 x) :*: I (I0 y) :*: U
ETup x y -> R . R . L $ I (I0 x) :*: I (I0 y) :*: U
EIntLit n -> R . R . R . L $ K n :*: U
ETyped e t -> R . R . R . R $ I (I0 e) :*: I (I0 t) :*: U
from Type ty = R . Tag $ case ty of
TyInt -> L $ U
TyTup x y -> R $ I (I0 x) :*: I (I0 y) :*: U
to Expr (L (Tag ex)) = case ex of
L (I (I0 x) :*: I (I0 y) :*: U) -> EAdd x y
R (L (I (I0 x) :*: I (I0 y) :*: U)) -> EMul x y
R (R (L (I (I0 x) :*: I (I0 y) :*: U))) -> ETup x y
R (R (R (L (K n :*: U)))) -> EIntLit n
R (R (R (R (I (I0 x) :*: I (I0 y) :*: U)))) -> ETyped x y
to Type (R (Tag ty)) = case ty of
L U -> TyInt
R (I (I0 x) :*: I (I0 y) :*: U) -> TyTup x y
-- $(deriveConstructors [''Expr, ''Type])
-- $(deriveFamily ''AST [''Expr, ''Type] "PFAST")
-- type instance PF AST = PFAST
-- inferTypeExpr :: ErrorAlg (PF_Expr :>: Expr) String Type
-- inferTypeExpr = undefined & undefined & undefined & undefined & undefined
--
-- inferTypeType :: ErrorAlg (PF_Type :>: Type) String Type
-- inferTypeType = undefined & undefined
--
-- inferType :: ErrorAlg (PF_Tuples) String Type
-- inferType = inferTypeExpr & inferTypeType
-- inferType :: ErrorAlg (PF Tuples) String Type
type ExprErrorAlg e a
= (a -> a -> Either e a)
:&: (a -> a -> Either e a)
:&: (a -> a -> Either e a)
:&: (Int -> Either e a)
:&: (a -> a -> Either e a)
type TypeErrorAlg e a
= Either e a
:&: (a -> a -> Either e a)
-- inferType :: ExprErrorAlg String Type :&: TypeErrorAlg String Type
inferType :: ErrorAlg (PF Tuples) String Type
inferType = ( equal "+" & equal "*" & tup & const (Right TyInt) & equal "::" )
& ( Right TyInt & tup )
where
equal op ty1 ty2
| ty1 == ty2 = Right ty1
| otherwise = Left ("lhs and rhs of " ++ op ++ " must have equal types")
tup ty1 ty2 = Right (TyTup ty1 ty2)
type (:&:) = (,)
infixr :&: