Formatting function types
(→Seel also: link to old rant)
m (→Seel also: seel -> see)
Latest revision as of 14:17, 11 July 2011
A very common way (at least in the base libraries) of formatting function types seems to be this:
hPutBuf :: Handle -- handle to write to -> Ptr a -- address of buffer -> Int -- number of bytes of data in buffer -> IO ()
I remember when I first started learning Haskell, and these many-arrowed functions seemed very strange to me: "Okay, we give it a handle, and get a pointer, and, um, from this we get an int, and from this an action? Er?"
The problem here is that the first parameter has a distinguished look while the other parameters and the return value all look the same. I think that a naive reader is inclined to assume that line breaks are situated at major structural boundaries. Consider two different interpretations of the structure of the type term:
(((Handle (Handle -> Ptr a) ->(Ptr a -> Int) ->(Int -> IO ()) -> IO ())))
Which one looks more natural?
The point of this rant is just this: the aforementioned multi-line formatting style should only be used for left-associative infix operators. For right-associative ones (such as the function arrow), the One True Way is this:
Handle -> Ptr a -> Int -> IO ()
Unfortunately the first (misleading) style is used by Haddock for library documentation and GHC for error reporting.