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 eitherLeft
orRight
(2)
content
is a value of typeHtml(Msg)
(3)
content
has valuep [] []
Let's evaluate
content
...(4)
p
is a function of typep : 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 typep : List (Attribute xtype) -> List (Html xtype) -> Html xtype
In Java syntax that would be something like
(4x)
p
is a function of typep<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 typeMsg
:(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 beList (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 beList (Html Msg)
. No problem with that either.p
with[] []
.Html Msg
.How is that possible if
p
doesn't know much aboutMsg
?Invoke mathematical constraint-based thinking and conclude that
p [] []
must resolve to a value of typeHtml x
for every typex
. This is only possible if it resolves to a value that does not vary inx
- a constant completely independent ofx
. Thereforep [] []
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 typemsg
and returns stuff containing values of typemsg
, maybe trivially so ifp
always returns a constant completely not involving anything of typemsg
. It will keep anymsg
as it was (because it has not been given any function transformingmsg
), just shift them around somehow.See also: "Theorems for Free!" by Philp Wadler, 1989 for going deeper into this. Wadler starts off with this: