{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module PolyList
(
PolyList (..)
, HEntry (..)
, pLength
, pHead
) where
import Data.Kind (Constraint, Type)
type family All (c :: Type -> Constraint) (ts :: [Type]) :: Constraint where
All _ '[] = ()
All c (t : ts) = (c t, All c ts)
data PolyList (ts :: [Type]) where
PNil :: PolyList '[]
(:#) :: t -> PolyList ts -> PolyList (t ': ts)
infixr 5 :#
instance All Eq ts => Eq (PolyList ts) where
PolyList ts
PNil == :: PolyList ts -> PolyList ts -> Bool
== PolyList ts
PNil = Bool
True
(t
a :# PolyList ts
as) == (t
b :# PolyList ts
bs) = t
a t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
t
b Bool -> Bool -> Bool
&& PolyList ts
as PolyList ts -> PolyList ts -> Bool
forall a. Eq a => a -> a -> Bool
== PolyList ts
PolyList ts
bs
instance (All Eq ts, All Ord ts) => Ord (PolyList ts) where
PolyList ts
PNil compare :: PolyList ts -> PolyList ts -> Ordering
`compare` PolyList ts
PNil = Ordering
EQ
compare (t
a :# PolyList ts
as) (t
b :# PolyList ts
bs) = t -> t -> Ordering
forall a. Ord a => a -> a -> Ordering
compare t
a t
t
b Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> PolyList ts -> PolyList ts -> Ordering
forall a. Ord a => a -> a -> Ordering
compare PolyList ts
as PolyList ts
PolyList ts
bs
instance (All Show ts) => Show (PolyList ts) where
show :: PolyList ts -> String
show PolyList ts
PNil = String
"PNil"
show (t
a :# PolyList ts
as) = t -> String
forall a. Show a => a -> String
show t
a String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" :# " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> PolyList ts -> String
forall a. Show a => a -> String
show PolyList ts
as
pLength :: PolyList ts -> Int
pLength :: forall (ts :: [*]). PolyList ts -> Int
pLength PolyList ts
PNil = Int
0
pLength (t
_ :# PolyList ts
ts) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PolyList ts -> Int
forall (ts :: [*]). PolyList ts -> Int
pLength PolyList ts
ts
pHead :: PolyList (t ': ts) -> t
pHead :: forall t (ts :: [*]). PolyList (t : ts) -> t
pHead (t
t :# PolyList ts
_) = t
t
t
data HEntry = forall a. Show a => HEntry a
instance Show HEntry where
show :: HEntry -> String
show (HEntry a
a) = a -> String
forall a. Show a => a -> String
show a
a