
On Sat, Mar 13, 2010 at 3:19 AM, wren ng thornton
The usual approach I've seen is not to distinguish strict and lazy datatypes, but rather to distinguish strict and lazy functions, e.g. by having two different arrows: (->) for lazy functions and (!->) for strict ones.[1]
But what about the laziness properties of e.g. the maybe function? ghci> maybe undefined id (Just ()) () ghci> maybe () undefined Nothing () ghci> maybe undefined id Nothing *** Exception: Prelude.undefined ghci> maybe () undefined (Just ()) *** Exception: Prelude.undefined It's clear that no type signature for maybe is going to tell you about all these cases. It's similarly impossible to imagine a type signature that will tell you that take 3 is strict up to the third nested cons of the input list, and no further. In general, laziness behaviour can get complicated quickly and so I'm not convinced that the type signature is a good home for that information. I suppose a function arrow that had the same effect as putting a ! pattern on the parameter to its left might not be a bad thing (although we could argue about the exact syntax and representation, as imo !-> is neither intuitively obvious nor aesthetically pleasing), but it's never going to make seq and ! patterns (which can be applied on a single equation rather than the whole function, and in nested/lambda bindings) and so forth redundant.