{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
module Chapter05() where
import Control.Monad.Trans.Class (MonadTrans)
import Data.Kind(Constraint, Type)
data Expr a where
LitInt :: Int -> Expr Int
LitBool :: Bool -> Expr Bool
Add :: Expr Int -> Expr Int -> Expr Int
Not :: Expr Bool -> Expr Bool
If :: Expr Bool -> Expr a -> Expr a -> Expr a
evalExpr :: Expr a -> a
evalExpr (LitInt i) = i
evalExpr (LitBool b) = b
evalExpr (Add x y) = evalExpr x + evalExpr y
evalExpr (Not x) = not $ evalExpr x
evalExpr (If b x y ) =
if evalExpr b
then evalExpr x
else evalExpr y
ex1 :: Expr Int
ex1 = If (LitBool False ) ( LitInt 1) (Add ( LitInt 5) (LitInt 13))
-- >>>evalExpr ex1
-- 18
newtype SepHList (ts :: [Type])= SepHList (HList ts)
instance Show (SepHList '[]) where
show (SepHList HNil) = ""
instance (Show t, Show (SepHList ts)) => Show (SepHList (t:ts)) where
show (SepHList as) =
case as of
a :# HNil -> show a
a :# as -> show a <> ", " <> show (SepHList as)
instance Show (HList '[]) where
show HNil = ""
instance (Show t, Show (HList ts), Show (SepHList ts)) => Show (HList (t ': ts)) where
show as = "[ " <> show (SepHList as) <> " ]"
-- >>>p2
-- [ "Hou", False, 3, True ]
type family AllEq (ts :: [Type]) :: Constraint where
AllEq '[] = ()
AllEq (t ': ts) = (Eq t, AllEq ts)
-- >>>:kind! AllEq '[Int, Bool]
-- AllEq '[Int, Bool] :: Constraint
-- = (Eq Int, (Eq Bool, () :: Constraint))