packages feed

vinyl-0.1.0.0: Data/Vinyl/Rec.hs

{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}

module Data.Vinyl.Rec
  ( Rec(..)
  , (=:)
  , (<+>)
  ) where

import Data.Vinyl.Field
import GHC.TypeLits

-- A record is parameterized by a list of fields.
data Rec :: [*] -> * where
  RNil :: Rec '[]
  (:&) :: (f ~ (sy ::: t)) => (f, t) -> Rec fs -> Rec (f ': fs)
infixr :&

-- Appends records
(<+>) :: Rec as -> Rec bs -> Rec (as ++ bs)
RNil      <+> xs = xs
(x :& xs) <+> ys =  x :& (xs <+> ys)
infixl 8 <+>

-- Shorthand for a record with a single field
(=:) :: sy ::: t -> t -> Rec '[sy ::: t]
a =: b = (a, b) :& RNil

-- Type level list append
type family (as :: [*]) ++ (bs :: [*]) :: [*]
type instance '[] ++ bs = bs
type instance (a ': as) ++ bs  = a ': (as ++ bs)


instance Show (Rec '[]) where
  show RNil = "{}"
instance (SingI sy, Show t, Show (Rec fs)) => Show (Rec ((sy ::: t) ': fs)) where
  show ((k,x) :& xs) = show k ++ " :=: " ++ show x ++ ", " ++ show xs


instance Eq (Rec '[]) where
  _ == _ = True
instance (Eq t, Eq (Rec fs)) => Eq (Rec ((s ::: t) ': fs)) where
  ((_,x) :& xs) == ((_,y) :& ys) = (x == y) && (xs == ys)