5

When I try to compile this with ghc it complains the number of parameters in the left hand sides of the function definition are different.

module Example where

import Data.Maybe

from_maybe :: a -> Maybe a -> a
from_maybe a Nothing = a
from_maybe _ = Data.Maybe.fromJust

I'm wondering whether this is a ghc restriction. I tried to see if I could find anything about the number of parameters in the Haskell 2010 Report but I wasn't successful.

Is this legal Haskell or isn't it? If not, where is this parameter count restriction listed?

Marc van Dongen
  • 534
  • 4
  • 15
  • 1
    Possible duplicate of [Defining a function by equations with different number of arguments](https://stackoverflow.com/questions/8745597/defining-a-function-by-equations-with-different-number-of-arguments) – amalloy Nov 01 '17 at 17:27
  • 1
    @amalloy I don't think it's an exact dupe. – melpomene Nov 01 '17 at 17:35
  • Don't vote to close it, then. That's why closing a question takes 5 votes. – amalloy Nov 01 '17 at 17:48
  • 1
    @melpomene I agree, the [linked question](https://stackoverflow.com/questions/8745597/defining-a-function-by-equations-with-different-number-of-arguments) asks for a *reason* behind the decision. this one asks for the reference into the spec. – Will Ness Nov 01 '17 at 18:40
  • 1
    @amalloy Keep in mind, you are closing in on the gold `[haskell]` badge, which would allow you to close a question as a duplicate by yourself. – chepner Nov 01 '17 at 18:41
  • @chepner or re-open. (I think) :) – Will Ness Nov 01 '17 at 18:42
  • [yes](https://meta.stackexchange.com/a/231212/172601), re-open too. – Will Ness Nov 01 '17 at 18:50
  • It's not relevant to the question, but... I'm curious about why you use `fromJust` (which is partial, and should be avoided), but do not use `fromMaybe` (which is total) and instead redefine it. – chi Nov 01 '17 at 19:30
  • Thanks to all. All I needed was a reference to the section in the language definition that posed the restriction. – Marc van Dongen Nov 01 '17 at 21:10

2 Answers2

20

It's not legal. The restriction is described in the Haskell 2010 Report:

4.4.3.1 Function bindings

[...]

Note that all clauses defining a function must be contiguous, and the number of patterns in each clause must be the same.

Community
  • 1
  • 1
melpomene
  • 84,125
  • 8
  • 85
  • 148
0

The answer from melpomene is the summation of the syntax rules. In this answer I want to try to describe why this has to be the case.

From the point of view of the programmer, the syntax in the question seems quite reasonable. There is a first specific case which is marked by a value in the second parameter. Then there is a general solution which reduces to an existing function. Either pattern on its own is valid so why can they not co-exist?

The syntax rule that all patterns must capture exactly the same parameters is a necessary result of haskell being a lazy language. Being lazy means that the values of parameters are not evaluated until they are needed.

Let's look at what happens when we curry a function, that is provide it with less then the number of parameters in the declaration. When that happens haskell produces an anonymous function* that will complete the function and stores the first parameters in the scope of that function without evaluating them.

That last part is important. For functions with different numbers of parameters, it would be necessary to evaluate some of them to choose which pattern to match, but then not evaluate them.

In other words the compiler needs to know exactly how many parameters it needs before it evaluates them to choose among the patterns. So while it seems like we should not need to put an extra _ in, the compiler needs it to be there.

As an aside, the order in which parameters occur can make a big difference in how easy a function is to implement and use. See the answers to my question Ordering of parameters to make use of currying for suggestions. If the order is reversed on the example function, it can be implemented with only the one named point.

from_maybe :: Maybe a -> a -> a
from_maybe Nothing = id
from_maybe (Just x) = const x

*: What an implementation like GHC actually does in this situation is subject to optimization and may not work exactly this way, but the end result must be the same as if it did.

John F. Miller
  • 26,961
  • 10
  • 71
  • 121
  • 3
    "*the compiler needs to know exactly how many parameters it needs before it evaluates them to choose among the patterns*" - no, it doesn't. What problems are you thinking of? – melpomene Nov 01 '17 at 22:48
  • 1
    Case in point: Agda nowadays supports clauses with a different number of patterns which is super convenient when a pattern can cause the RHS to be a function type, and you want to pattern-match on that extra argument. – gallais Nov 02 '17 at 15:06
  • Agda's semantics are not lazy so the problem of evaluation order does not come up. Agda is a total language, i.e., each program in it must terminate and all possible patterns must be matched. Without this feature, the logic behind the language becomes inconsistent, and it becomes possible to prove arbitrary statements. Haskell is not total and so evaluation order is significant and function reduction must be consistent. I stand by my answer. – John F. Miller Nov 02 '17 at 23:51
  • I don't see how that makes a difference. Agda is also sensible to the order in which clauses are declared. And being too strict in a pattern will block some reductions that would happen otherwise. This variable number of arguments could very well be adapted as an extension to Haskell. – gallais Nov 03 '17 at 14:18