SML# Document Version 4.1.0
13 SML# feature: dynamic types and typed manipulation of JSON

13.1 Dynamic typing

In dynamically-typed languages, the users are allowed to perform operations depending on the types of values at runtime. A value in a dynamically-typed language is a uniform data structure consisting of the runtime representation of a type and a value of the type. SML# provides a mechanism to deal with this dynamically-typed data structures.

The Dynamic.void Dynamic.dyn type is the type of dynamically-typed values. The meaning of Dynamic.void shall be described below. The following primitives are given for this type:

  • The function Dynamic.dynamic : [’a#reify. ’a -> Dynamic.void Dynamic.dyn]. This introduces a dynamically-typed value from an arbitrary ML value. ’a#reify indicates that the runtime type information of the instance of ’a is required. Unlike other type kinds, the reify kind does not restrict the set of types over which the type variable ranges.

  • The expression _dynamic exp as τ. This checks the type information of dynamically-typed value exp at runtime and casts it to the type τ. If the cast failed, the runtime exception Dynamic.RuntimeTypeError is raised.

Furthermore, the following expression is provided:

_dynamiccase exp of dpat1 => exp1 | | dpatn => expn

This performs dynamic type check and pattern matching with a dynamically-typed value exp. A pattern dpati may be an arbitrary ML pattern except that variable patterns must be type-annotated.

The following interactive session is an example of a heterogenous list and functions proceeding it.

# val x = Dynamic.dynamic {name = "Sendai", wind = 7.6};
val x = _ : Dynamic.void Dynamic.dyn
# val y = Dynamic.dynamic {name = "Shiroishi", weather = "Sunny"};
val y = _ : Dynamic.void Dynamic.dyn
# val z = Dynamic.dynamic {name = "Ishinomaki", temp = 12.4};
val z = _ : Dynamic.void Dynamic.dyn
# val l = [x, y, z];
val l = [_, _, _] : Dynamic.void Dynamic.dyn list
# fun getName r = _dynamiccase r of {name:string, ...} => name;
val getName = fn : [’a. ’a Dynamic.dyn -> string]
# map getName l;
val it = ["Sendai", "Shiroishi", "Ishinomaki"] : string list
# fun getTemp r =
>     _dynamiccase r of
>       {temp:real, ...} => SOME temp
>     | _ : Dynamic.void Dynamic.dyn => NONE;
val getTemp = fn : [’a. ’a Dynamic.dyn -> real option]
# map getTemp l;
val it = [NONE, NONE, SOME 12.4] : real option list

Dynamically-typed values are not restricted to records; values of arbitrary types, such as datatypes, functions, and opaque types, can become dynamically-typed values and get back to statically-typed values.