Formatting function types

From HaskellWiki
Revision as of 14:17, 11 July 2011 by Lemming (talk | contribs) (→‎Seel also: seel -> see)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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.


See also