0

Sometimes, if one the pattern rules need some special rhs which is made more readable via where, I end up with something like this

data D = A | B | C
func :: D -> b
func A = special_case
  where
    special_case = other helper
    other = aaaa
    helper = bbb
func _ = bla

where the catch-all pattern seems to be so far from the other pattern, because of the lengthy where. It'd be nice if I could write something like this:

func :: D -> b
func !A = bla -- imaginary syntax
func A = special_case
  where
    special_case = other helper
    other = aaaa
    helper = bbb

I don't think it would still be called catch-all, but rather "catch-all-but", but is there any way to do this?

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • It comes down to your style preference, but my first reaction to this would be to refactor the `where` clause to be smaller, or use only one equation with a `case` expression and a shared `where` at the end. I find that multi-equation functions help me mainly when the cases are long and distinct, and readability benefits from some redundancy in the function name. They’re unhelpful if the cases are very sensitive to order, need to share a lot, or repeat multiple parameters. – Jon Purdy Feb 21 '21 at 00:44

1 Answers1

4

If you don't need to bind anything, you could do something like this:

isA :: D -> Bool
isA A = True
isA _ = False

func :: D -> b
func d | not (isA d) = bla
func A = special_case where ...

(You could alternately implement isn'tA to avoid the not. But while I've seen functions like isA defined every so often, I don't believe I've ever seen an analog of isn'tA in the wild.)

It might not be obvious to the compiler that this match is complete. You could fix that like this:

type A'sFields = () -- your specific D doesn't have any fields for A,
                    -- but this pattern is general enough to use for
                    -- constructors that do

fromA :: D -> Maybe A'sFields
fromA A = Just ()
fromA _ = Nothing

func :: D -> b
func d = case fromA d of
    Nothing -> bla
    Just () -> special_case where ...
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380