compdata-0.3: benchmark/Functions/Comp/Inference.hs
{-# LANGUAGE
TemplateHaskell,
MultiParamTypeClasses,
FlexibleInstances,
FlexibleContexts,
UndecidableInstances,
TypeOperators,
ScopedTypeVariables,
TypeSynonymInstances #-}
module Functions.Comp.Inference where
import Functions.Comp.Desugar
import DataTypes.Comp
import Data.Comp
import Data.Comp.Derive
-- type inference
class Monad m => InferType f t m where
inferTypeAlg :: f (Term t) -> m (Term t)
inferType :: (Traversable f, InferType f t m) => Term f -> m (Term t)
inferType = cataM inferTypeAlg
inferBaseType :: (Traversable f, InferType f ValueT m) => Term f -> m BaseType
inferBaseType = inferType
$(derive [liftSum] [''InferType])
instance (ValueT :<: t, Monad m) => InferType Value t m where
inferTypeAlg (VInt _) = return $ inject TInt
inferTypeAlg (VBool _) = return $ inject TBool
inferTypeAlg (VPair x y) = return $ inject $ TPair x y
checkOp :: (g :<: f, Eq (g (Term f)), Monad m) =>
[g (Term f)] -> g (Term f) -> [Term f] -> m (Term f)
checkOp exs et tys = if and (zipWith (\ f t -> maybe False (==f) (project t)) exs tys)
then return (inject et)
else fail""
instance (ValueT :<: t, EqF t, Monad m) => InferType Op t m where
inferTypeAlg (Plus x y) = checkOp [TInt,TInt] TInt [x ,y]
inferTypeAlg (Mult x y) = checkOp [TInt,TInt] TInt [x ,y]
inferTypeAlg (Lt x y) = checkOp [TInt,TInt] TBool [x ,y]
inferTypeAlg (And x y) = checkOp [TBool,TBool] TBool [x ,y]
inferTypeAlg (Not x) = checkOp [TBool] TBool [x]
inferTypeAlg (If b x y) = case project b of
Just TBool | x == y -> return x
_ -> fail ""
inferTypeAlg (Eq x y) = if x == y then return iTBool else fail ""
inferTypeAlg (Proj p x) = case project x of
Just (TPair x1 x2) ->
case p of
ProjLeft -> return x1
ProjRight -> return x2
_ -> fail ""
instance (ValueT :<: t, EqF t, Monad m) => InferType Sugar t m where
inferTypeAlg (Minus x y) = checkOp [TInt,TInt] TInt [x ,y]
inferTypeAlg (Neg x) = checkOp [TInt] TInt [x]
inferTypeAlg (Gt x y) = checkOp [TInt,TInt] TBool [x ,y]
inferTypeAlg (Or x y) = checkOp [TBool,TBool] TBool [x ,y]
inferTypeAlg (Impl x y) = checkOp [TBool,TBool] TBool [x ,y]
desugType :: SugarExpr -> Err BaseType
desugType = inferType . (desug :: SugarExpr -> Expr)
typeSugar :: SugarExpr -> Err BaseType
typeSugar = inferType
desugTypeAlg :: AlgM Err SugarSig BaseType
desugTypeAlg = inferTypeAlg `compAlgM'` (desugAlg :: TermHom SugarSig ExprSig)
desugType' :: SugarExpr -> Err BaseType
desugType' e = cataM desugTypeAlg e
-- pure type inference
class InferType2 f t where
inferTypeAlg2 :: f (Term t) -> (Term t)
inferType2 :: (Functor f, InferType2 f t) => Term f -> (Term t)
inferType2 = cata inferTypeAlg2
inferBaseType2 :: (Functor f, InferType2 f ValueT) => Term f -> BaseType
inferBaseType2 = inferType2
$(derive [liftSum] [''InferType2])
instance (ValueT :<: t) => InferType2 Value t where
inferTypeAlg2 (VInt _) = inject TInt
inferTypeAlg2 (VBool _) = inject TBool
inferTypeAlg2 (VPair x y) = inject $ TPair x y
checkOp2 :: (g :<: f, Eq (g (Term f))) =>
[g (Term f)] -> g (Term f) -> [Term f] -> (Term f)
checkOp2 exs ret tys = if and (zipWith (\ f t -> maybe False (==f) (project t)) exs tys)
then inject ret
else error ""
instance (ValueT :<: t, EqF t) => InferType2 Op t where
inferTypeAlg2 (Plus x y) = checkOp2 [TInt,TInt] TInt [x ,y]
inferTypeAlg2 (Mult x y) = checkOp2 [TInt,TInt] TInt [x ,y]
inferTypeAlg2 (Lt x y) = checkOp2 [TInt,TInt] TBool [x ,y]
inferTypeAlg2 (And x y) = checkOp2 [TBool,TBool] TBool [x ,y]
inferTypeAlg2 (Not x) = checkOp2 [TBool] TBool [x]
inferTypeAlg2 (If b x y) = case project b of
Just TBool | x == y -> x
_ -> error ""
inferTypeAlg2 (Eq x y) = if x == y then iTBool else error ""
inferTypeAlg2 (Proj p x) = case project x of
Just (TPair x1 x2) ->
case p of
ProjLeft -> x1
ProjRight -> x2
_ -> error ""
instance (ValueT :<: t, EqF t) => InferType2 Sugar t where
inferTypeAlg2 (Minus x y) = checkOp2 [TInt,TInt] TInt [x ,y]
inferTypeAlg2 (Neg x) = checkOp2 [TInt] TInt [x]
inferTypeAlg2 (Gt x y) = checkOp2 [TInt,TInt] TBool [x ,y]
inferTypeAlg2 (Or x y) = checkOp2 [TBool,TBool] TBool [x ,y]
inferTypeAlg2 (Impl x y) = checkOp2 [TBool,TBool] TBool [x ,y]
desugType2 :: SugarExpr -> BaseType
desugType2 = inferType2 . (desug :: SugarExpr -> Expr)
typeSugar2 :: SugarExpr -> BaseType
typeSugar2 = inferType2
desugTypeAlg2 :: Alg SugarSig BaseType
desugTypeAlg2 = inferTypeAlg2 `compAlg` (desugAlg :: TermHom SugarSig ExprSig)
desugType2' :: SugarExpr -> BaseType
desugType2' e = cata desugTypeAlg2 e