Difference between revisions of "Formatting function types"
(→Seel also: link to old rant) |
m (New category) |
||
(2 intermediate revisions by 2 users not shown) | |||
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 |
||
Line 43: | Line 61: | ||
− | == |
+ | ==See also== |
* Lauri Alanko in Haskell Cafe on [http://www.haskell.org/pipermail/haskell-cafe/2002-November/003617.html Formatting function types] |
* Lauri Alanko in Haskell Cafe on [http://www.haskell.org/pipermail/haskell-cafe/2002-November/003617.html Formatting function types] |
||
Line 49: | Line 67: | ||
[[Category:Syntax]] |
[[Category:Syntax]] |
||
+ | [[Category:Rants_and_comments]] |
Latest revision as of 08:15, 23 May 2021
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
- Lauri Alanko in Haskell Cafe on Formatting function types
- and once again with more participants