Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
This module helps to visualize and debug the BuiltinMeaning
inference machinery from the
Elaborate
and Meaning
modules.
Synopsis
- elaborateDebug :: forall a j. ElaborateFromTo DefaultUni 0 j (Term TyName Name DefaultUni DefaultFun ()) a => a -> a
- makeBuiltinMeaningDebug :: forall a. MakeBuiltinMeaning a (Term TyName Name DefaultUni DefaultFun ()) => a -> a
- module PlutusCore.Name.Unique
- module PlutusCore.Default
- module PlutusCore.Core
- newtype Opaque val (rep :: Type) = Opaque {
- unOpaque :: val
- newtype SomeConstant uni (rep :: Type) = SomeConstant {
- unSomeConstant :: Some (ValueOf uni)
- data TyNameRep (kind :: Type) = TyNameRep Symbol Nat
- data family TyVarRep (name :: TyNameRep kind) :: kind
- data family TyAppRep (fun :: dom -> cod) (arg :: dom) :: cod
- data family TyForallRep (name :: TyNameRep kind) (a :: Type) :: Type
- data family BuiltinHead x
- type family ElaborateBuiltin uni x
- type family AllElaboratedArgs constr x where ...
- class AllElaboratedArgs constr (ElaborateBuiltin uni x) => AllBuiltinArgs uni constr x
- type family FoldArgs args res where ...
- data BuiltinMeaning val cost = forall args res. BuiltinMeaning (TypeScheme val args res) ~(FoldArgs args res) (cost -> BuiltinRuntime val)
- type HasMeaningIn uni val = (Typeable val, ExMemoryUsage val, HasConstantIn uni val)
- class (Typeable uni, Typeable fun, Bounded fun, Enum fun, Ix fun, Default (BuiltinSemanticsVariant fun)) => ToBuiltinMeaning uni fun where
- type CostingPart uni fun
- data BuiltinSemanticsVariant fun
- toBuiltinMeaning :: HasMeaningIn uni val => BuiltinSemanticsVariant fun -> fun -> BuiltinMeaning val (CostingPart uni fun)
- withTypeSchemeOfBuiltinFunction :: forall val fun r. (ToBuiltinMeaning (UniOf val) fun, ExMemoryUsage val, Typeable val, HasConstant val) => BuiltinSemanticsVariant fun -> fun -> (forall args res. TypeScheme val args res -> r) -> r
- typeOfBuiltinFunction :: forall uni fun. ToBuiltinMeaning uni fun => BuiltinSemanticsVariant fun -> fun -> Type TyName uni ()
- type family GetArgs a where ...
- class KnownMonotype val args res where
- knownMonotype :: TypeScheme val args res
- toMonoF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val
- class KnownMonotype val args res => KnownPolytype (binds :: [Some TyNameRep]) val args res where
- knownPolytype :: TypeScheme val args res
- toPolyF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val
- type family ThrowOnBothEmpty binds args isBuiltin a where ...
- class MakeBuiltinMeaning a val where
- makeBuiltinMeaning :: a -> (cost -> FoldArgs (GetArgs a) ExBudgetStream) -> BuiltinMeaning val cost
- toBuiltinRuntime :: cost -> BuiltinMeaning val cost -> BuiltinRuntime val
- toBuiltinsRuntime :: (cost ~ CostingPart uni fun, ToBuiltinMeaning uni fun, HasMeaningIn uni val) => BuiltinSemanticsVariant fun -> cost -> BuiltinsRuntime fun val
- module PlutusCore.Builtin.Elaborate
Documentation
elaborateDebug :: forall a j. ElaborateFromTo DefaultUni 0 j (Term TyName Name DefaultUni DefaultFun ()) a => a -> a Source #
Instantiate type variables in the type of a value using ElaborateFromTo
. Example usages:
>>>
:t elaborateDebug False
elaborateDebug False :: Bool>>>
:t elaborateDebug fst
elaborateDebug fst :: (TyVarRep ('TyNameRep "a" 0), TyVarRep ('TyNameRep "b" 1)) -> TyVarRep ('TyNameRep "a" 0)
makeBuiltinMeaningDebug :: forall a. MakeBuiltinMeaning a (Term TyName Name DefaultUni DefaultFun ()) => a -> a Source #
module PlutusCore.Name.Unique
module PlutusCore.Default
module PlutusCore.Core
newtype Opaque val (rep :: Type) Source #
The AST of a value with a Plutus type attached to it. The type is for the Plutus type checker
to look at. Opaque
can appear in the type of the denotation of a builtin.
Instances
newtype SomeConstant uni (rep :: Type) Source #
For unlifting from the Constant
constructor when the stored value is of a monomorphic
built-in type
The rep
parameter specifies how the type looks on the PLC side (i.e. just like with
Opaque val rep
).
SomeConstant | |
|
Instances
data TyNameRep (kind :: Type) Source #
Representation of a type variable: its name and unique and an implicit kind.
Instances
data family TyVarRep (name :: TyNameRep kind) :: kind Source #
Representation of an intrinsically-kinded type variable: a name.
Instances
(tyname ~ TyName, name ~ ('TyNameRep text uniq :: TyNameRep a), KnownSymbol text, KnownNat uniq) => KnownTypeAst tyname uni (TyVarRep name :: a) Source # | |
(TypeError NoStandalonePolymorphicDataErrMsg :: Constraint) => Contains uni (TyVarRep :: TyNameRep kind -> kind) Source # | |
type ToBinds uni acc (TyVarRep name :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type IsBuiltin uni (TyVarRep name :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type ToHoles uni (TyVarRep name :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst |
data family TyAppRep (fun :: dom -> cod) (arg :: dom) :: cod Source #
Representation of an intrinsically-kinded type application: a function and an argument.
Instances
(KnownTypeAst tyname uni fun, KnownTypeAst tyname uni arg) => KnownTypeAst tyname uni (TyAppRep fun arg :: a) Source # | |
type ToBinds uni acc (TyAppRep fun arg :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type IsBuiltin uni (TyAppRep fun arg :: a) Source # | |
type ToHoles uni (TyAppRep fun arg :: a) Source # | |
data family TyForallRep (name :: TyNameRep kind) (a :: Type) :: Type Source #
Representation of of an intrinsically-kinded universal quantifier: a bound name and a body.
Instances
(tyname ~ TyName, name ~ ('TyNameRep text uniq :: TyNameRep kind), KnownSymbol text, KnownNat uniq, KnownKind kind, KnownTypeAst tyname uni a) => KnownTypeAst tyname uni (TyForallRep name a :: Type) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst type IsBuiltin uni (TyForallRep name a) :: Bool Source # type ToHoles uni (TyForallRep name a) :: [Hole] Source # type ToBinds uni acc (TyForallRep name a) :: [Some TyNameRep] Source # | |
type ToBinds uni acc (TyForallRep name a :: Type) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type IsBuiltin uni (TyForallRep name a :: Type) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type ToHoles uni (TyForallRep name a :: Type) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst |
data family BuiltinHead x Source #
For annotating an uninstantiated built-in type, so that it gets handled by the right instance or type family.
Instances
Contains uni f => KnownTypeAst tyname uni (BuiltinHead f :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst type IsBuiltin uni (BuiltinHead f) :: Bool Source # type ToHoles uni (BuiltinHead f) :: [Hole] Source # type ToBinds uni acc (BuiltinHead f) :: [Some TyNameRep] Source # | |
type ToBinds uni acc (BuiltinHead f :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type IsBuiltin uni (BuiltinHead f :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst | |
type ToHoles uni (BuiltinHead f :: a) Source # | |
Defined in PlutusCore.Builtin.KnownTypeAst |
type family ElaborateBuiltin uni x Source #
Take an iterated application of a built-in type and elaborate every function application
inside of it to TyAppRep
and annotate the head with BuiltinHead
.
The idea is that we don't need to process built-in types manually if we simply add some
annotations for instance resolution to look for. Think what we'd have to do manually for, say,
ToHoles
: traverse the spine of the application and collect all the holes into a list, which is
troubling, because type applications are left-nested and lists are right-nested, so we'd have to
use accumulators or an explicit Reverse
type family. And then we also have KnownTypeAst
and
ToBinds
, so handling built-in types in a special way for each of those would be a hassle,
especially given the fact that type-level Haskell is not exactly good at computing things.
With the ElaborateBuiltin
approach we get KnownTypeAst
, ToHoles
and ToBinds
for free.
We make this an open type family, so that elaboration is customizable for each universe.
Instances
type ElaborateBuiltin DefaultUni (x :: a) Source # | |
Defined in PlutusCore.Default.Universe |
type family AllElaboratedArgs constr x where ... Source #
Take a constraint and use it to constrain every argument of a possibly 0-ary elaborated application of a built-in type.
AllElaboratedArgs constr (f `TyAppRep` x) = (constr x, AllElaboratedArgs constr f) | |
AllElaboratedArgs _ (BuiltinHead _) = () |
class AllElaboratedArgs constr (ElaborateBuiltin uni x) => AllBuiltinArgs uni constr x Source #
Take a constraint and use it to constrain every argument of a possibly 0-ary application of a built-in type.
Instances
AllElaboratedArgs constr (ElaborateBuiltin uni x) => AllBuiltinArgs uni constr (x :: a) Source # | |
Defined in PlutusCore.Builtin.Polymorphism |
type family FoldArgs args res where ... Source #
Turn a list of Haskell types args
into a functional type ending in res
.
>>>
:set -XDataKinds
>>>
:kind! FoldArgs [(), Bool] Integer
FoldArgs [(), Bool] Integer :: * = () -> Bool -> Integer
data BuiltinMeaning val cost Source #
The meaning of a built-in function consists of its type represented as a TypeScheme
,
its Haskell denotation and its uninstantiated runtime denotation.
The TypeScheme
of a built-in function is used for example for
- computing the PLC type of the function to be used during type checking
- getting arity information
- generating arbitrary values to apply the function to in tests
The denotation is lazy, so that we don't need to worry about a builtin being bottom (happens in tests). The production path is not affected by that, since only runtime denotations are used for evaluation.
forall args res. BuiltinMeaning (TypeScheme val args res) ~(FoldArgs args res) (cost -> BuiltinRuntime val) |
type HasMeaningIn uni val = (Typeable val, ExMemoryUsage val, HasConstantIn uni val) Source #
Constraints available when defining a built-in function.
class (Typeable uni, Typeable fun, Bounded fun, Enum fun, Ix fun, Default (BuiltinSemanticsVariant fun)) => ToBuiltinMeaning uni fun where Source #
A type class for "each function from a set of built-in functions has a BuiltinMeaning
".
type CostingPart uni fun Source #
The cost
part of BuiltinMeaning
.
data BuiltinSemanticsVariant fun Source #
See Note [Builtin semantics variants]
toBuiltinMeaning :: HasMeaningIn uni val => BuiltinSemanticsVariant fun -> fun -> BuiltinMeaning val (CostingPart uni fun) Source #
Get the BuiltinMeaning
of a built-in function.
Instances
withTypeSchemeOfBuiltinFunction :: forall val fun r. (ToBuiltinMeaning (UniOf val) fun, ExMemoryUsage val, Typeable val, HasConstant val) => BuiltinSemanticsVariant fun -> fun -> (forall args res. TypeScheme val args res -> r) -> r Source #
Feed the TypeScheme
of the given built-in function to the continuation.
typeOfBuiltinFunction :: forall uni fun. ToBuiltinMeaning uni fun => BuiltinSemanticsVariant fun -> fun -> Type TyName uni () Source #
Get the type of a built-in function.
class KnownMonotype val args res where Source #
A class that allows us to derive a monotype for a builtin.
We could've computed the runtime denotation from the
TypeScheme
and the denotation of the builtin, but not statically (due to unfolding not working
for recursive functions and TypeScheme
being recursive, i.e. requiring the conversion function
to be recursive), and so it would cause us to retain a lot of evaluation-irrelevant stuff in the
constructors of BuiltinRuntime
, which has to make evaluation slower (we didn't check) and
certainly makes the generated Core much harder to read. Technically speaking, we could get
a RuntimeScheme
from the TypeScheme
and the denotation statically if we changed the
definition of TypeScheme
and made it a singleton, but then the conversion function would have
to become a class anyway and we'd just replicate what we have here, except in a much more
complicated way.
knownMonotype :: TypeScheme val args res Source #
toMonoF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val Source #
Convert the denotation of a builtin to its runtime counterpart .
The argument is in ReadKnownM
, because that's what deferred unlifting amounts to:
passing the action returning the builtin application around until full saturation, which is
when the action actually gets run.
Instances
(Typeable res, KnownTypeAst TyName (UniOf val) res, MakeKnown val res) => KnownMonotype val ('[] :: [Type]) res Source # | Once we've run out of term-level arguments, we return a
|
Defined in PlutusCore.Builtin.Meaning knownMonotype :: TypeScheme val '[] res Source # toMonoF :: ReadKnownM (FoldArgs '[] res, FoldArgs '[] ExBudgetStream) -> BuiltinRuntime val Source # | |
(Typeable arg, KnownTypeAst TyName (UniOf val) arg, MakeKnown val arg, ReadKnown val arg, KnownMonotype val args res) => KnownMonotype val (arg ': args) res Source # | Every term-level argument becomes a |
Defined in PlutusCore.Builtin.Meaning knownMonotype :: TypeScheme val (arg ': args) res Source # toMonoF :: ReadKnownM (FoldArgs (arg ': args) res, FoldArgs (arg ': args) ExBudgetStream) -> BuiltinRuntime val Source # |
class KnownMonotype val args res => KnownPolytype (binds :: [Some TyNameRep]) val args res where Source #
A class that allows us to derive a polytype for a builtin.
knownPolytype :: TypeScheme val args res Source #
toPolyF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val Source #
Convert the denotation of a builtin to its runtime counterpart.
The argument is in ReadKnownM
, because that's what we need to do:
passing the action returning the builtin application around until full saturation, which is
when the action actually gets run.
Instances
KnownMonotype val args res => KnownPolytype ('[] :: [Some TyNameRep]) val args res Source # | Once we've run out of type-level arguments, we start handling term-level ones. |
Defined in PlutusCore.Builtin.Meaning knownPolytype :: TypeScheme val args res Source # toPolyF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val Source # | |
(KnownSymbol name, KnownNat uniq, KnownKind kind, KnownPolytype binds val args res) => KnownPolytype ('Some ('TyNameRep name uniq :: TyNameRep kind) ': binds) val args res Source # | Every type-level argument becomes a |
Defined in PlutusCore.Builtin.Meaning knownPolytype :: TypeScheme val args res Source # toPolyF :: ReadKnownM (FoldArgs args res, FoldArgs args ExBudgetStream) -> BuiltinRuntime val Source # |
type family ThrowOnBothEmpty binds args isBuiltin a where ... Source #
Ensure a built-in function is not nullary and throw a nice error otherwise.
ThrowOnBothEmpty '[] '[] 'True a = TypeError (('Text "A built-in function must take at least one type or term argument" ':$$: ((('Text "\8216" ':<>: 'ShowType a) ':<>: 'Text "\8217 is a built-in type") ':<>: 'Text " so you can embed any of its values as a constant")) ':$$: 'Text "If you still want a built-in function, add a dummy \8216()\8217 argument") | |
ThrowOnBothEmpty '[] '[] 'False a = TypeError ('Text "A built-in function must take at least one type or term argument" ':$$: 'Text "To fix this error add a dummy \8216()\8217 argument") | |
ThrowOnBothEmpty _ _ _ _ = () |
class MakeBuiltinMeaning a val where Source #
A function turned into a type class with exactly one fully general instance.
We can't package up the constraints of makeBuiltinMeaning
(see the instance) into a type or
class synonym, because they contain a bunch of variables defined by ~
or determined via
functional dependencies and neither class nor type definitions can handle that
(see https://gitlab.haskell.org/ghc/ghc/-/issues/7100). Inlining three lines of constraints
whenever we need to call makeBuiltinMeaning
over a non-concrete type is a bad option and this
abstraction is free anyway, hence its existence.
The a
type variable goes first, because makeBuiltinMeaning @A
is a common pattern.
makeBuiltinMeaning :: a -> (cost -> FoldArgs (GetArgs a) ExBudgetStream) -> BuiltinMeaning val cost Source #
Construct the meaning for a built-in function by automatically deriving its
TypeScheme
, given
- the denotation of the builtin
- an uninstantiated costing function
Instances
(uni ~ UniOf val, binds ~ ToBinds uni ('[] :: [Some TyNameRep]) a, args ~ GetArgs a, a ~ FoldArgs args res, ThrowOnBothEmpty binds args (IsBuiltin uni a) a, ElaborateFromTo uni 0 j val a, KnownPolytype binds val args res) => MakeBuiltinMeaning a val Source # | |
Defined in PlutusCore.Builtin.Meaning makeBuiltinMeaning :: a -> (cost -> FoldArgs (GetArgs a) ExBudgetStream) -> BuiltinMeaning val cost Source # |
toBuiltinRuntime :: cost -> BuiltinMeaning val cost -> BuiltinRuntime val Source #
Convert a BuiltinMeaning
to a BuiltinRuntime
given a cost model.
toBuiltinsRuntime :: (cost ~ CostingPart uni fun, ToBuiltinMeaning uni fun, HasMeaningIn uni val) => BuiltinSemanticsVariant fun -> cost -> BuiltinsRuntime fun val Source #
Calculate runtime info for all built-in functions given meanings of builtins (as a constraint), the semantics variant of the set of builtins and a cost model.
module PlutusCore.Builtin.Elaborate