{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Plutarch.DataRepr.Internal.HList (
HRec (HNil, HCons),
HRecGeneric (HRecGeneric),
Labeled (Labeled, unLabeled),
hrecField,
hrecField',
type IndexList,
type IndexLabel,
type SingleItem,
type Drop,
Elem (..),
ElemOf (..),
) where
import Data.Kind (Constraint, Type)
import GHC.Records (HasField, getField)
import GHC.TypeLits (Symbol)
import Plutarch.Builtin.Data (PAsData)
import Plutarch.DataRepr.Internal.FromData (PFromDataable, pmaybeFromAsData)
import Plutarch.DataRepr.Internal.HList.Utils (
Drop,
Elem (Here, There),
IndexLabel,
IndexList,
Labeled (Labeled, unLabeled),
SingleItem,
)
import Plutarch.Internal.Term (Term)
import Plutarch.Internal.TypeFamily (Snd)
type HRec :: [(Symbol, Type)] -> Type
data HRec as where
HNil :: HRec '[]
HCons :: Labeled name a -> HRec as -> HRec ('(name, a) ': as)
indexHRec :: HRec as -> (forall a. Elem a as -> Snd a)
indexHRec :: forall (as :: [(Symbol, Type)]).
HRec as
-> forall (a :: (Symbol, Type)).
Elem @(Symbol, Type) a as -> Snd @Type @Symbol a
indexHRec (HCons Labeled @Symbol name a
x HRec as
_) Elem @(Symbol, Type) a as
Here = Labeled @Symbol name a -> a
forall {k} (sym :: k) a. Labeled @k sym a -> a
unLabeled Labeled @Symbol name a
x
indexHRec (HCons Labeled @Symbol name a
_ HRec as
xs) (There Elem @(Symbol, Type) a as1
i) = HRec as
-> forall (a :: (Symbol, Type)).
Elem @(Symbol, Type) a as -> Snd @Type @Symbol a
forall (as :: [(Symbol, Type)]).
HRec as
-> forall (a :: (Symbol, Type)).
Elem @(Symbol, Type) a as -> Snd @Type @Symbol a
indexHRec HRec as
xs Elem @(Symbol, Type) a as
Elem @(Symbol, Type) a as1
i
indexHRec HRec as
HNil Elem @(Symbol, Type) a as
impossible = case Elem @(Symbol, Type) a as
impossible of {}
hrecField' ::
forall name a as.
ElemOf name a as =>
HRec as ->
a
hrecField' :: forall (name :: Symbol) a (as :: [(Symbol, Type)]).
ElemOf name a as =>
HRec as -> a
hrecField' HRec as
xs = HRec as
-> forall (a :: (Symbol, Type)).
Elem @(Symbol, Type) a as -> Snd @Type @Symbol a
forall (as :: [(Symbol, Type)]).
HRec as
-> forall (a :: (Symbol, Type)).
Elem @(Symbol, Type) a as -> Snd @Type @Symbol a
indexHRec HRec as
xs (Elem @(Symbol, Type) '(name, a) as
-> Snd @Type @Symbol '(name, a))
-> Elem @(Symbol, Type) '(name, a) as
-> Snd @Type @Symbol '(name, a)
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol) a (as :: [(Symbol, Type)]).
ElemOf name a as =>
Elem @(Symbol, Type) '(name, a) as
elemOf @name @a @as
type ElemOf :: Symbol -> Type -> [(Symbol, Type)] -> Constraint
class IndexLabel name as ~ a => ElemOf name a as | as name -> a where
elemOf :: Elem '(name, a) as
instance ElemOf name a ('(name, a) ': as) where
elemOf :: Elem '(name, a) ('(name, a) ': as)
elemOf :: Elem
@(Symbol, Type) '(name, a) ((':) @(Symbol, Type) '(name, a) as)
elemOf = Elem
@(Symbol, Type) '(name, a) ((':) @(Symbol, Type) '(name, a) as)
forall {k} (a :: k) (as1 :: [k]). Elem @k a ((':) @k a as1)
Here
instance
{-# OVERLAPPABLE #-}
( IndexLabel name (b ': as) ~ a
, ElemOf name a as
) =>
ElemOf name a (b ': as)
where
elemOf :: Elem '(name, a) (b ': as)
elemOf :: Elem @(Symbol, Type) '(name, a) ((':) @(Symbol, Type) b as)
elemOf = Elem @(Symbol, Type) '(name, a) as
-> Elem @(Symbol, Type) '(name, a) ((':) @(Symbol, Type) b as)
forall {k} (a :: k) (as1 :: [k]) (b :: k).
Elem @k a as1 -> Elem @k a ((':) @k b as1)
There (forall (name :: Symbol) a (as :: [(Symbol, Type)]).
ElemOf name a as =>
Elem @(Symbol, Type) '(name, a) as
elemOf @name @a @as)
hrecField ::
forall name c as a b s.
( ElemOf name a as
, Term s (PAsData b) ~ a
, PFromDataable b c
) =>
HRec as ->
Term s c
hrecField :: forall (name :: Symbol) (c :: PType) (as :: [(Symbol, Type)]) a
(b :: PType) (s :: S).
(ElemOf name a as, (Term s (PAsData b) :: Type) ~ (a :: Type),
PFromDataable b c) =>
HRec as -> Term s c
hrecField HRec as
xs =
forall (a :: PType) (b :: PType) (s :: S).
PFromDataable a b =>
Term s (PAsData a) -> Term s b
pmaybeFromAsData @b @c (Term s (PAsData b) -> Term s c) -> Term s (PAsData b) -> Term s c
forall a b. (a -> b) -> a -> b
$ forall (name :: Symbol) a (as :: [(Symbol, Type)]).
ElemOf name a as =>
HRec as -> a
hrecField' @name HRec as
xs
{-# DEPRECATED hrecField "please use getField from GHC.Records" #-}
instance
forall name c as a b s.
( IndexLabel name as ~ a
, ElemOf name a as
, Term s (PAsData b) ~ a
, PFromDataable b c
) =>
HasField name (HRec as) (Term s c)
where
getField :: HRec as -> Term s c
getField = forall (name :: Symbol) (c :: PType) (as :: [(Symbol, Type)]) a
(b :: PType) (s :: S).
(ElemOf name a as, (Term s (PAsData b) :: Type) ~ (a :: Type),
PFromDataable b c) =>
HRec as -> Term s c
hrecField @name
newtype HRecGeneric as = HRecGeneric (HRec as)
instance
forall name a as.
( IndexLabel name as ~ a
, ElemOf name a as
) =>
HasField name (HRecGeneric as) a
where
getField :: HRecGeneric as -> a
getField (HRecGeneric HRec as
x) = forall (name :: Symbol) a (as :: [(Symbol, Type)]).
ElemOf name a as =>
HRec as -> a
hrecField' @name HRec as
x