Std.Dynamic
View source →A typed, honest stand-in for a dynamically-shaped value — the well-typed
replacement for Any.
Dynamic is a single homogeneous tagged sum over Cure's real BEAM value
shapes: an atom, an integer, a float, a string, a list of Dynamic, a tuple
(as a list of Dynamic), or a map from Dynamic to Dynamic. Because every
leaf is itself a Dynamic, an arbitrarily-nested document — a decoded JSON
blob, a heterogeneous config — has one static type, and you narrow to a
concrete shape by pattern-matching a constructor rather than by an unchecked
runtime is_map/is_tuple guess.
This module knows nothing about optics: it is an ordinary stdlib citizen,
usable on its own by anyone who wants a typed Any. Std.Optic imports it to
offer per-constructor "case affines" (dyn_str : Affine(Dynamic, String), …),
but the dependency is one-way — Std.Dynamic never imports Std.Optic.
Examples
use Std.Dynamic
Int(3) # => Int(3)
match Str("hi") # => true
Str(s) -> true
other -> false
Types
-
type Dynamic = Atom | Int | Float | Str | List | Tuple | MapA dynamically-shaped value. One constructor per BEAM value shape; the container shapes (
List,Tuple,Map) recurse throughDynamic, so the whole thing is one type no matter how deeply nested the data is. -
type DynamicEntry = EntryOne key/value entry of a
Map. A dynamic map is an association list of these rather than an opaqueMap(Dynamic, Dynamic):Dynamicin the key position of an opaque map is not provably strictly positive (an opaque map could be function-backed, making the key contravariant), so the kernel rejects it — exactly as Idris/Agda reject a recursive occurrence through an abstract type. An explicit product whose definition the positivity checker can see is strictly positive in both fields, so the mutual recursionDynamic/DynamicEntryis accepted.
Functions
-
# fn entries(d: Dynamic) -> List(DynamicEntry)
The entries of a
Map, or the empty list for any other shape. Total: it never crashes on a mis-shaped value, it just yields no entries. -
# fn entry(k: Dynamic, v: Dynamic) -> DynamicEntry
Build one association-list entry of a
Map. -
# fn entry_key(e: DynamicEntry) -> Dynamic
Projections of a
DynamicEntryinto its key and value halves. -
# fn entry_value(e: DynamicEntry) -> Dynamic
-
# fn of_atom(a: Atom) -> Dynamic
Smart constructors: inject a native BEAM value into
Dynamic. These are the public way to build a dynamic value — prefer them over naming the raw constructors so callers do not depend on constructor spelling. -
# fn of_float(x: Float) -> Dynamic
-
# fn of_int(n: Int) -> Dynamic
-
# fn of_list(xs: List(Dynamic)) -> Dynamic
-
# fn of_map(es: List(DynamicEntry)) -> Dynamic
-
# fn of_str(s: String) -> Dynamic
-
# fn of_tuple(xs: List(Dynamic)) -> Dynamic
-
# fn tag(d: Dynamic) -> Atom
The shape tag of a dynamic value — a total discriminator, one atom per constructor. Use it to branch before narrowing with a
match.