{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE PatternSynonyms #-}
module Main where
import Generics.MultiRec hiding (show)
import Generics.MultiRec.TH
import Test.QuickCheck
import Test.QuickCheck.Random
import Control.Monad
import Generics.MultiRec.Transformations.Main
import Generics.MultiRec.Transformations.MemoTable
data Expr = Var String
| Const Int
| Neg Expr
| Add Expr Expr
deriving (Show, Ord, Eq)
data ExprAST :: * -> * where
Expr :: ExprAST Expr
type instance Ixs ExprAST = '[ Expr ]
$(deriveAll ''ExprAST)
instance Arbitrary Expr where
shrink (Var v) = map Var (shrink v)
shrink (Const v) = map Const (shrink v)
shrink (Neg l) = [l]
shrink (Add l r) = [l,r]
arbitrary = sized expr'
where expr' 0 = oneof [liftM Var arbitrary, liftM Const arbitrary]
expr' n | n>0 =
oneof [ liftM Var arbitrary
, liftM Const arbitrary
, liftM Neg (expr' (pred n))
, liftM2 Add subtree subtree ]
where subtree = expr' (n `div` 2)
expr1, expr2, expr3 :: Expr
expr1 = Add (Const 1) (Var "a")
expr2 = Add (Const 1) (Neg (Var "a"))
expr3 = Add (Var "a") (Const 1)