-
Notifications
You must be signed in to change notification settings - Fork 35
Map types
Map types can have optional associations K => V
and mandatory associations K := V
.
If a map type doesn't mention a key of a certain type, such keys are forbidden in maps of that type. For example, #{}
is the empty map type, so if a map value has any key at all, it is not a value of type #{}
.
Map types have the same syntax as map expressions, but with a different meaning of =>
and :=
, which may be confusing. We'll try to always use the words map type when we refer to a map type.
Subtyping for map types needs some documentation. Here is a draft.
A for subtyping in general, T1 is a subtype of T2 if all values/expressions/patterns of type T1 are also values/expressions/patterns of type T2. We use T1 :: T2 to denote subtyping. (It is actually compatible subtyping.)
- Type
#{}
: The empty map type has only one value: The empty map#{}
. No keys are allowed. - Type
#{a := b}
: A map with a mandatory key of typea
which maps to a value of typeb
. There is only one such map:#{a => b}
. - Type
#{a => b}
: A map with an optional keya
, so it has two values:#{a => b}
and#{}
.
We can see that #{} :: #{a => b}
and #{a := b} :: #{a => b}
.
Given two map types M1
, M2
.
M1 :: M2
if and only if the following two conditions are fulfilled:
-
For all associations
K1 <Assoc1> V1
inM1
, there exists an associationK2 <Assoc2> V2
inM2
such that-
K1 :: K2
, -
V1 :: V2
, -
<Assoc1>
is mandatory if<Assoc2>
is mandatory, - the association
K2 <Assoc2> V2
is the first association inM2
with a matching a keyK2
such thatK1 :: K2
.
The third bullet means that {Assoc1, Assoc2} must be one of the following three combinations:
{=>, =>}
,{:=, =>}
or{:=, :=}
.The forth bullet accounts for the quote "The key types in
AssociationList
are allowed to overlap, and if they do, the leftmost association takes precedence" from Erlang Types and Function Specifications. -
-
For all mandatory associations
K2 := V2
inM2
, there is a mandatory associationK1 := V1
inM1
such thatK1 :: K2
V1 :: V2
A mandatory key is typically a singleton such as a specific atom or integer, but what if a mandatory association is used for a non-singleton type as the key? We interpret it as that at least one key of the type is required.
Example: The type #{a | b :: c}
is a map type where a key of type a | b
is mandatory, i.e. a
or b
. Thus, the values of this type are #{a :: c}
, #{b :: c}
and #{a :: c, b :: c}
.