15

With multiple pattern-matching, different numbers of arguments are impossible, even with point-free!

foo True b = b + 2
foo _ = id

doesn't work for example. But

foo True = (+2)
foo _ = id

does. Sometimes we can use point-free only in one part of the function, so...

Why? Is it too hard for GHC? :'(

Will Ness
  • 70,110
  • 9
  • 98
  • 181
L01man
  • 1,521
  • 10
  • 27
  • 4
    It's generally considered bad form. Different number of arguments for a set of function definitions is generally indicative of an error. – Thomas M. DuBuisson Jul 14 '12 at 20:34
  • 6
    It's possible to write well typed functions whose arity changes depending on the value of its arguments. Perhaps that's a minority sport, but it makes the restriction that left-hand sides must have the same number of arguments something of an artificial restriction, not to mention a nuisance. It's true that lhs mismatch is often an error, but why not let the type system catch them? – pigworker Jul 14 '12 at 20:59
  • I think it's more convenient and readability is not affected. Checking that the types are the same and translating `id` to `(\x -> id x)` would be easy for the compiler, I guess. – L01man Jul 14 '12 at 21:47
  • 2
    It's a perfectly reasonable thing to allow varying number of arguments. And it would be easy to compile. The choice not to allow it is just a matter of style. – augustss Jul 15 '12 at 01:34
  • +1 I have wondered this myself. – Dan Burton Jul 15 '12 at 01:43
  • See the `unpl` function of http://www.haskell.org/haskellwiki/Pointfree which does that. – L01man Jul 15 '12 at 08:04

2 Answers2

20

Why? Is it too hard for GHC?

No. It is not at all too hard for GHC. Actually, this is the fault of the Haskell Report.

See: Haskell Report 2010 > Declarations and Bindings > Function bindings

A function binding binds a variable to a function value. The general form of a function binding for variable x is:

x p11 … p1k match1

x pn1 … pnk matchn

[...blah blah...]

Translation: The general binding form for functions is semantically equivalent to the equation (i.e. simple pattern binding):

x = \ x1 … xk -> case (x1, …, xk) of

(p11, …, p1k) match1

(pn1, …, pnk) matchn
where the xi are new identifiers.

(emphasis mine)

While function definitions are semantically equivalent to a lambda & case expression, they are not necessarily compiled that way, as Mihai suggests.

The thing is, the Haskell report defines function declarations such that they must have the same number of inputs on the left-hand side of the equation. This is made clear by the fact that k remains the same on both the 1st and the nth function declaration lines (and by implication, all lines in-between). This is the reason for the restriction; it has nothing to do with GHC's implementation details.

tl;dr

The choice not to allow it is just a matter of style. – augustss

Dan Burton
  • 53,238
  • 27
  • 117
  • 198
4

Each function equation must have the same number of arguments. This is why your first example fails.

To fix it, use

foo True b = b + 2
foo _ x = id x

As you see, both equations have the same number of arguments.

Multiple equations involving pattern matching are translated into case expressions. In your case foo gets translated roughly as

foo a b = case a of
    True -> b + 2
    _ -> id x

Both (all) branches of the case must have the same type, thus you first example which would be translated as

foo a b = case a of
    True -> b + 2
    _ -> id

is wrong because the branches have different types.

Of course, this is hand waving, the actual things happening behind the scenes are more complicated

Mihai Maruseac
  • 20,967
  • 7
  • 57
  • 109
  • But calling `foo ` with one argument does the same thing in both cases. – L01man Jul 14 '12 at 20:46
  • 4
    Simply expanding a simple function definition with one equation to a λ-expression explains very little here, what's more important is that definitions with _multiple_ equations are transformed into a _single_ equation with multiple `case` selections. Which doesn't really work when the equations are η-reduced to a different degree. – leftaroundabout Jul 14 '12 at 21:02
  • 1
    So pattern-matching on the left side desugars to a case expression? – L01man Jul 14 '12 at 21:04
  • @L01man: Yes, I think that's exactly how it works. – Tikhon Jelvis Jul 14 '12 at 21:33
  • My bad, I was thinking of something else. Updated the answer with the right explanation (thanks for @leftaroundabout which showed where I was wrong). Indeed, in the Core we have only `case` expressions for pattern matching – Mihai Maruseac Jul 14 '12 at 21:40