Skip to content

Pattern synonym types should reveal their arity

I was playing around with Pattern Synonyms, when I realized that their reported type are not informative enough as they should be.

Take the following pattern synonym as an example

returns4 f | f 2 == 4   = Just f
           | otherwise = Nothing

pattern Returns4 f <- (returns4 -> (Just f))
  where Returns4 _ = const 4

Other than the non-data return type, there is nothing special about Returns4.

Okay, now that we have defined Returns4 let's ask GHCi about its type.

Returns4 :: forall {a}. (Num a, Eq a) => (a -> a) -> a -> a

Okay, that seems fair.

"I" know that patterns, unlike functions, should always be saturated. So let's define a function that uses Returns4:

testing (Returns4 f 2) = ...
testing _              = ...

Wait, why is GHC complaining that I've passed an extra argument to Returns4?

The pattern synonym ‘Returns4’ should have 1 argument, but has been given 2
• In the pattern: Returns4 f 2
In an equation for ‘testing’:
testing (Returns4 f 2)
= ...

Because the arity of Returns4 is not reflected in its type. I.e the more intuitive type for Returns4 would be the following:

Returns4 :: forall {a}. (Num a, Eq a) => (a -> a) -> (a -> a)

It looks much better now!

Even though GHC's error message is very informative and simple, I still think it's worthwhile to enclose Non-Data function return types in parenthesis.

Edited by Artin Ghasivand
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information