Difference between revisions of "Formatting function types"

From HaskellWiki
Jump to navigation Jump to search
m (→‎Seel also: seel -> see)
(Add summation analogy)
Line 12: Line 12:
 
a pointer, and, um, from this we get an int, and from this an action?
 
a pointer, and, um, from this we get an int, and from this an action?
 
Er?"
 
Er?"
  +
  +
''I'd like to interject here for a moment. The way to read a Signature in that style is similar to reading a multiline summation. e.g''
  +
  +
<table>
  +
<tr><td>
  +
hPutBuf :: Handle
  +
-> Ptr a
  +
-> Int
  +
-> IO ()
  +
</td><td>
  +
hPutBuf: Handle
  +
+ Ptr a
  +
+ Int
  +
-------------
  +
= IO ()
  +
</td></tr>
  +
</table>
  +
'' I aggree with the argument, that for beginners it is hard to see what a function returns, but that has to do with currying. A right associative way for defining a function signature would (only in this case and worse in others) be easier to read.''
   
 
The problem here is that the first parameter has a distinguished look
 
The problem here is that the first parameter has a distinguished look

Revision as of 09:04, 16 May 2017

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?"

I'd like to interject here for a moment. The way to read a Signature in that style is similar to reading a multiline summation. e.g

 hPutBuf :: Handle
         -> Ptr a 
         -> Int   
         -> IO ()
 hPutBuf:   Handle
          + Ptr a 
          + Int
        ------------- 
          = IO ()

I aggree with the argument, that for beginners it is hard to see what a function returns, but that has to do with currying. A right associative way for defining a function signature would (only in this case and worse in others) be easier to read.

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