I have the following code, that I do not understand:
type Msg
= Left | Right
content : Html Msg
content =
p [] []
The type signature of p
:
p : List (Attribute msg) -> List (Html msg) -> Html msg
The question is, why p
can return the type of Msg
in the content
function. I know that Html msg
and msg
can any variable but it does not return either Left
or Right
.
I will take a shot at this (not particularly trained in ML languages or Lambda calculus, and worked with '{}' carrying languages for far too long, so some of my vocabulary may be off):
(1) Msg
is a type that specializes to either Left
or Right
(2) content
is a value of type Html(Msg)
(3) content
has value p [] []
Let's evaluate content
...
(4) p
is a function of type p : List (Attribute msg) -> List (Html msg) -> Html msg
In the expression above msg
is a type variable, we could also write, less confusingly:
(4a) p
is a function of type p : List (Attribute xtype) -> List (Html xtype) -> Html xtype
In Java syntax that would be something like
(4x) p
is a function of type p<XType> : List (Attribute<XType>) -> List (Html<XType>) -> Html<XType>
So we have the following constraint on p [] []
:
p : List (Attribute xtype) -> List (Html xtype) -> Html xtype
Html Msg
this immediately tells us that unknown type xtype
must actually be type Msg
:
(5) p : List (Attribute Msg) -> List (Html Msg) -> Html Msg
The first argument to p
is []
. According to the constrained signature above, the type of that expression must be List (Attribute Msg)
. No problem with that, the elm type checking theorem proving engine lets this through.
The second argument to p
is []
. According to the constrained signature above, the type of that expression must be List (Html Msg)
. No problem with that either.
p
with [] []
. Html Msg
.How is that possible if p
doesn't know much about Msg
?
Invoke mathematical constraint-based thinking and conclude that p [] []
must resolve to a value of type Html x
for every type x
. This is only possible if it resolves to a value that does not vary in x
- a constant completely independent of x
. Therefore p [] []
resolves to some trivial value. However the poodle's core of the mathematical assertion:
p : List (Attribute msg) -> List (Html msg) -> Html msg
is that p
is something that takes stuff containing values of type msg
and returns stuff containing values of type msg
, maybe trivially so if p
always returns a constant completely not involving anything of type msg
. It will keep any msg
as it was (because it has not been given any function transforming msg
), just shift them around somehow.
See also: "Theorems for Free!" by Philp Wadler, 1989 for going deeper into this. Wadler starts off with this: