
On Jul 17, 2021, at 7:21 AM, Simon Marlow
wrote: Hi Richard - I'm curious about the coding style that you would advocate that uses it often. Can you give an example?
Sure:
not :: Bool -> Bool not = \cases False -> True True -> False
filter :: (a -> Bool) -> [a] -> [a] filter = \cases _ [] -> [] pred (x : xs) | pred x -> x : filter pred xs | otherwise -> filter pred xs
This style has a few advantages over the more typical one: - The name is not repeated each time, which is otherwise a refactoring hazard. - The indentation of each line does not depend on the name, which is otherwise a separate refactoring hazard. - It is possible to define a helper function in a where clause that scopes over the whole function. Alternative version of filter
filter :: (a -> Bool) -> [a] -> [a] filter pred = \cases [] -> [] (x : xs) | pred x -> x : filtered | otherwise -> filtered where filtered = filter pred xs
This alternative has further advantages: - It is clear which parameters are matched against and which are not (assuming the matched parameters go last). - A `where` clause can scope over the whole function, or an individual match, depending on its indentation level. A style more at odds with history might be
filter :: forall a. (a -> Bool) -> [a] -> [a] = \cases ...
which is even less repetitive. Would I *require* any of this for all of Haskell? Never. But it's appealing to me in its concision and expressive power. Richard