Thursday, April 18, 2019

[nzfpggsk] Type annotations on operators

In Haskell, one can assert the type of an identifier in an expression by attaching a type annotation with "::".  For infix operators, one can attach such a type annotation by rewriting it in function notation: surround the operator with parentheses and move it from infix to prefix position:

three :: Int;
three = ((+)::Int -> Int -> Int) 1 2;

It seems impossible to attach a type annotation to an operator while keeping it in infix notation.  This is a bit problematic because a common use of an infix operator is to use many of them in series, e.g., 1 + 2 + 3 + 4, but it is awkward to rewrite a long series of uses of an infix operator into prefix notation.

ten = (+) ((+) ((+) 1 2) 3) 4

Tangentially, for addition, we could do foldl' (+) 0 [1, 2, 3, 4], but fold won't work with operators like (.), ($), or (>>=) which take operands of many different types within a series expression.  Previously: syntactic fold and fold (.) via Data.Dynamic.

The motivation was, if one is using a polymorphic function or operator, it may be pedagogically helpful to attach a type annotation at the point of use so the reader knows what "version" of a polymorphic function is being invoked.  The annotation gives the concrete types at the point of use, rather than the polymorphic type with type variables that library documentation will give you.

A nice (hypothetical) IDE could do type inference to figure out the type at the point of use, then display it as a popup.

No comments :