Formerly Morgan-Stanley/morphir-elm. Search finds this package by either name.
Like any other programming languages Morphir has a type system as well. This module defines the building blocks of that type system. If you want to learn more about type systems check out Wikipedia: Type system.
Morphir's type system is heavily inspired by Elm's type system so the best way to understand the building blocks here is through some Elm examples. Let's take this bit of Elm code as a starting point:
type alias MyInteger =
Int
type alias MyRecord a =
{ foo : List a
}
type Foo a
= Bar a
| BazThese would translate to type definitions in Morphir which is represented by the Definition type.
Definitions themselves don't have a name. It's the Module that contains that information in the types dictionary as a
key. The type parameters and the right-hand side of the declaration is contained in the Definition type
itself. This is how the above would translate to the IR (some parts are omitted to reduce noise):
{ types =
Dict.fromList
[ ( [ "my", "integer" ], TypeAliasDefinition [] (...) )
, ( [ "my", "record" ], TypeAliasDefinition [ [ "a" ] ] (...) )
, ( [ "foo" ], CustomTypeDefinition [ [ "a" ], [ "b" ] ] (...) )
]
, values =
Dict.empty
}Type aliases simply assign a new name to a type expression. This type expression can be a reference to another type or a record type or any other type expression. Custom types are defined by a list of constructors. Each of those constructors have a list of arguments. Each argument is a type expression.
Here is the full definition for reference:
{ types =
Dict.fromList
[ ( [ "my", "integer" ]
, TypeAliasDefinition []
(Reference (fqn "Morphir.SDK" "Basics" "Int") [])
)
, ( [ "my", "record" ]
, TypeAliasDefinition [ [ "a" ] ]
(Record ()
[ Field [ "foo" ] (Reference () (fqn "Morphir.SDK" "List" "List") [ Variable () [ "a" ] ])
]
)
)
, ( [ "foo" ]
, CustomTypeDefinition [ [ "a" ], [ "b" ] ]
(AccessControlled.public
[ Constructor [ "bar" ] [ ( [ "arg", "1" ], Variable () [ "a" ] ) ]
, Constructor [ "baz" ] [ ( [ "arg", "1" ], Variable () [ "b" ] ) ]
]
)
)
]
, values =
Dict.empty
}Creates a type variable.
toIR a == variable [ "a" ] ()
toIR fooBar == variable [ "foo", "bar" ] ()Creates a fully-qualified reference to a type.
toIR (List Int)
== reference SDK.List.listType [ intType ]
toIR Foo.Bar
== reference
( [ [ "my" ], [ "lib" ] ], [ [ "foo" ] ], [ "bar" ] )
[]Creates a tuple type.
toIR ( Int, Bool )
== tuple [ basic intType, basic boolType ]Creates a record type.
toIR {} == record []
toIR { foo = Int }
== record
[ field [ "foo" ] SDK.Basics.intType
]
toIR { foo = Int, bar = Bool }
== record
[ field [ "foo" ] SDK.Basics.intType
, field [ "bar" ] SDK.Basics.boolType
]Creates an extensible record type.
toIR { e | foo = Int }
== extensibleRecord (variable [ "e" ])
[ field [ "foo" ] intType
]
toIR { f | foo = Int, bar = Bool }
== extensibleRecord (variable [ "f" ])
[ field [ "foo" ] intType
, field [ "bar" ] boolType
]Creates a function type. Use currying to create functions with more than one argument.
toIR (Int -> Bool) ==
function
SDK.Basics.intType
SDK.Basics.boolType
toIR (Int -> Bool -> Char) ==
function
intType
(function
SDK.Basics.boolType
SDK.Basics.charType
)An opaque representation of a field. It's made up of a name and a type.
Map the name of the field to get a new field.
Map the type of the field to get a new field.
This syntax represents a type definition. For example:
type alias Foo a = {bar : Maybe a, qux : Int}type MyList a = End | Cons a (MyList a)In the definition, the List Name refers to type parameters on the LHS
and Type extra refers to the RHS
Collect all variables in a type recursively.
Represents a type expression that can appear in various places within the IR. It can be the right-hand-side of a type alias declaration, input and output types of a function or as an annotation on values after type inference is done.
Type are modeled as expression trees: a recursive data structure with various node types. The type argument
aallows us to assign some additional attributes to each node in the tree. Here are some details on each node type in the tree:Int,String, ...) don't have an associated definition.Unit.a -> b -> cis represented asa -> (b -> c)