{-# OPTIONS_GHC -fno-warn-missing-methods #-}
{-# LANGUAGE DataKinds,
TypeOperators,
PolyKinds,
GADTs,
TypeInType,
RankNTypes,
StandaloneDeriving,
FlexibleInstances,
FlexibleContexts,
ConstraintKinds,
MultiParamTypeClasses,
FunctionalDependencies,
UndecidableInstances,
ScopedTypeVariables,
TypeFamilies,
InstanceSigs,
AllowAmbiguousTypes,
TypeApplications,
PatternSynonyms
#-}
module Data.GenRec
(
Rec(ConsRec, EmptyRec),
TagField(TagField),
WrapField,
UnWrap,
untagField,
(.=.),
(#),
(.*.),
Cmp,
ShowRec,
ShowField,
OpLookup(OpLookup),
lookup,
OpExtend(OpExtend),
OpUpdate(OpUpdate),
update,
emptyGenRec,
module Data.GenRec.Label
) where
import Data.Kind
import Data.Proxy
import Data.GenRec.Label
import Data.Type.Require
import Prelude hiding (lookup)
import GHC.TypeLits
type family a == b where
a == b = Equal a b
data Rec (c :: k) (r :: [(k', k'')]) :: Type where
EmptyRec :: Rec c '[]
ConsRec :: TagField c l v -> Rec c r -> Rec c ('( l, v) ': r)
emptyGenRec = EmptyRec
data TagField (c :: k) (l :: k') (v :: k'') where
TagField :: Label c -> Label l -> WrapField c v -> TagField c l v
infix 4 .=.
(l :: Label l) .=. (v :: v) = TagField Label l v
type family WrapField (c :: k') (v :: k) :: Type
type family UnWrap (t :: Type) :: [(k,k')]
type instance UnWrap (Rec c (r :: [(k, k')])) = (r :: [(k, k')])
untagField :: TagField c l v -> WrapField c v
untagField (TagField lc lv v) = v
type family Cmp (a :: k) (b :: k) :: Ordering
type instance Cmp (a :: Symbol) (b :: Symbol) = CmpSymbol a b
type family ShowRec c :: Symbol
type family ShowField c :: Symbol
data OpLookup (c :: Type)
(l :: k)
(r :: [(k, k')]) :: Type where
OpLookup :: Label l -> Rec c r -> OpLookup c l r
data OpLookup' (b :: Ordering)
(c :: Type)
(l :: k)
(r :: [(k, k')]) :: Type where
OpLookup' :: Proxy b -> Label l -> Rec c r -> OpLookup' b c l r
instance
Require (OpLookup' (Cmp l l') c l ('( l', v) ': r)) ctx
=>
Require (OpLookup c l ('( l', v) ': r)) ctx where
type ReqR (OpLookup c l ('( l', v) ': r)) =
ReqR (OpLookup' (Cmp l l') c l ('( l', v) ': r))
req ctx (OpLookup l r) =
req ctx (OpLookup' (Proxy @(Cmp l l')) l r)
instance
Require (OpError (Text "field not Found on " :<>: Text (ShowRec c)
:$$: Text "looking up the " :<>: Text (ShowField c)
:<>: Text " " :<>: ShowTE l
)) ctx
=>
Require (OpLookup c l ( '[] :: [(k,k')])) ctx where
type ReqR (OpLookup c l ('[] :: [(k,k')]) ) = ()
req = undefined
instance
Require (OpLookup' 'EQ c l ( '(l, v) ': r)) ctx where
type ReqR (OpLookup' 'EQ c l ( '(l, v) ': r)) =
WrapField c v
req Proxy (OpLookup' Proxy Label (ConsRec f _)) =
untagField f
instance (Require (OpLookup c l r) ctx)
=>
Require (OpLookup' 'GT c l ( '(l', v) ': r)) ctx where
type ReqR (OpLookup' 'GT c l ( '(l', v) ': r)) =
ReqR (OpLookup c l r)
req ctx (OpLookup' Proxy l (ConsRec _ r)) =
req ctx (OpLookup l r)
instance Require (OpError (Text "field not Found on " :<>: Text (ShowRec c)
:$$: Text "looking up the " :<>: Text (ShowField c)
:<>: Text " " :<>: ShowTE l
)) ctx
=>
Require (OpLookup' 'LT c l ( '(l', v) ': r)) ctx where
type ReqR (OpLookup' 'LT c l ( '(l', v) ': r)) = ()
req ctx (OpLookup' Proxy l (ConsRec _ r)) = ()
(#) :: RequireR (OpLookup c l r) '[] v =>
Rec c r -> Label l -> v
r # l = req (Proxy @ '[]) (OpLookup l r)
data OpUpdate (c :: Type)
(l :: k)
(v :: k')
(r :: [(k, k')]) :: Type where
OpUpdate :: Label l -> WrapField c v -> Rec c r
-> OpUpdate c l v r
data OpUpdate' (b :: Ordering)
(c :: Type)
(l :: k)
(v :: k')
(r :: [(k, k')]) :: Type where
OpUpdate' :: Proxy b -> Label l -> WrapField c v -> Rec c r
-> OpUpdate' b c l v r
instance (Require (OpUpdate' (Cmp l l') c l v ( '(l', v') ': r) ) ctx )
=>
Require (OpUpdate c l v ( '(l', v') ': r) ) ctx where
type ReqR (OpUpdate c l v ( '(l', v') ': r) ) =
ReqR (OpUpdate' (Cmp l l') c l v ( '(l', v') ': r) )
req ctx (OpUpdate l f r) =
(req @(OpUpdate' (Cmp l l') _ _ v _ ))
ctx (OpUpdate' (Proxy @(Cmp l l')) l f r)
instance (Require (OpError (Text "field not Found on " :<>: Text (ShowRec c)
:$$: Text "updating the " :<>: Text (ShowField c)
:<>: ShowTE l)) ctx)
=>
Require (OpUpdate c l v '[]) ctx where
type ReqR (OpUpdate c l v ('[] ) ) = Rec c '[]
req = undefined
instance
Require (OpUpdate' 'EQ c l v ( '(l, v') ': r)) ctx where
type ReqR (OpUpdate' 'EQ c l v ( '(l, v') ': r)) =
Rec c ( '(l, v) ': r)
req ctx (OpUpdate' proxy label field (ConsRec tgf r)) =
ConsRec (TagField Label label field) r
instance
( Require (OpUpdate c l v r) ctx
, ( '(l', v') : r0) ~ a
, ReqR (OpUpdate c l v r) ~ Rec c r0
)
=>
Require (OpUpdate' 'GT c l v ( '(l',v') ': r)) ctx where
type ReqR (OpUpdate' 'GT c l v ( '(l',v') ': r)) =
Rec c ( '(l',v') ': (UnWrap (ReqR (OpUpdate c l v r))))
req ctx (OpUpdate' _ l f (ConsRec field (r :: Rec c r))) =
ConsRec field $ (req @(OpUpdate _ _ v r)) ctx (OpUpdate l f r)
instance (Require (OpError (Text "field not Found on " :<>: Text (ShowRec c)
:$$: Text "updating the " :<>: Text (ShowField c)
:<>: ShowTE l)) ctx)
=>
Require (OpUpdate' 'LT c l v ( '(l',v') ': r)) ctx where
type ReqR (OpUpdate' 'LT c l v ( '(l',v') ': r)) =
()
req = undefined
update (l :: Label l) (v :: v) (r :: Rec c r) =
req Proxy (OpUpdate @l @c @v @r l v r)
lookup (l :: Label l) (r :: Rec c r) =
req Proxy (OpLookup @c @l @r l r)
data OpExtend (c :: Type)
(l :: k)
(v :: k')
(r :: [(k, k')]) :: Type where
OpExtend :: Label l -> WrapField c v -> Rec c r
-> OpExtend c l v r
data OpExtend' (b :: Ordering)
(c :: Type)
(l :: k)
(v :: k')
(r :: [(k, k')]) :: Type where
OpExtend' :: Proxy b -> Label l -> WrapField c v -> Rec c r
-> OpExtend' b c l v r
instance
Require (OpExtend c l v '[]) ctx where
type ReqR (OpExtend c l v '[]) =
Rec c '[ '(l , v)]
req ctx (OpExtend l v EmptyRec) =
ConsRec (TagField (Label @c) l v) EmptyRec
instance
Require (OpExtend' (Cmp l l') c l v ('(l', v') : r)) ctx
=>
Require (OpExtend c l v ( '(l', v') ': r)) ctx where
type ReqR (OpExtend c l v ( '(l', v') ': r)) =
ReqR (OpExtend' (Cmp l l') c l v ( '(l', v') ': r))
req ctx (OpExtend l v (r :: Rec c ( '(l', v') ': r)) ) =
req ctx (OpExtend' @(Cmp l l') @l @c @v Proxy l v r)
instance
(Require (OpExtend c l v r) ctx
, ( '(l', v') ': r0 ) ~ a
, ReqR (OpExtend c l v r) ~ Rec c r0
)
=>
Require (OpExtend' 'GT c l v ( '(l', v') ': r)) ctx where
type ReqR (OpExtend' 'GT c l v ( '(l', v') ': r)) =
Rec c ( '(l', v') ': UnWrap (ReqR (OpExtend c l v r)))
req ctx (OpExtend' Proxy l v (ConsRec lv r)) =
ConsRec lv $ req ctx (OpExtend @_ @_ @v l v r)
instance
Require (OpExtend' 'LT c l v ( '(l', v') ': r)) ctx where
type ReqR (OpExtend' 'LT c l v ( '(l', v') ': r)) =
Rec c ( '(l, v) ': ( '(l', v') ': r))
req ctx (OpExtend' Proxy l v r) =
ConsRec (TagField Label l v) r
instance
(Require (OpError (Text "cannot extend " :<>: Text (ShowRec c)
:$$: Text "colision in " :<>: Text (ShowField c)
:<>: Text " ":<>: ShowTE l)) ctx)
=>
Require (OpExtend' 'EQ c l v ( '(l, v') ': r)) ctx where
type ReqR (OpExtend' 'EQ c l v ( '(l, v') ': r)) = ()
req ctx = undefined
infixr 2 .*.
(TagField c l v :: TagField c l v) .*. (r :: Rec c r) =
req emptyCtx (OpExtend @l @c @v @r l v r)