1

I would'n expect this expression to work:

[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch) -- [(1, 'a'), (1, 'b'), ...]

because n should be out of scope in the second lambda. Apparently the second lambda is a closure of the first one:

[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch)))

What I don't understand is the underlying rule. How can the compiler decide that the second lambda is a closure of the first one without this being apparent from the syntax?

In this expression such a behavior wouldn't even make sense:

\x -> x + 1 . \y -> x + y
  • 3
    well all operators, functions bind "closer" (have lower precedence) than a lambda epxression, so it is just a consequence of operator precedence. – Willem Van Onsem Jan 06 '19 at 20:40
  • 2
    Whether or not `\x -> x + 1 . \y -> x + y` makes sense semantically isn't relevant to the question of it from being *syntactically* valid. – chepner Jan 06 '19 at 20:51

1 Answers1

2

In short: Typically the syntactical correctness is a step in compilers/interpreters that is done before the semantical correctness check (type systems, etc.). There are good reasons to separate the two.

What I don't understand is the underlying rule. How can the compiler decide that the second lambda is a closure of the first one without this being apparent from the syntax?

The Haskell compiler (like most, if not nearly all reasonable languages) are not apparent of the semantics, or the type system when they parse expressions. This is a consequence of the language grammar as described in the Haskell '98 report.

The body of a lambda expression thus extends as far to the right as possible (without hitting closing parenthesis.

In this expression such a behavior wouldn't even make sense:

\x -> x + 1 . \y -> x + y

No perhaps not. But typically parsing is done without knowledge of the types. Since that would be "unstable". Imagine that you write 2 + 3 * 4. Most people will see this as 2 + (3 * 4), perhaps some languages will interpret this differently, but eventually programmers get used to that. Now imagine that whether or not 3 being a float results in interpreting the expression differently, so 2 + 3.0 * 4 then all of a sudden is interpreted as (2 + 3.0) * 4. Here one can still say that the language has some explicit rules. But if later on, we replace 2, 3 and 4 by an identifier, then we are really getting into trouble, since altering the type of that identifier, could give a totally different meaning to a lot of expressions in the program.

In general it however frequently makes sense to extend lambda expressions to the right, as you found out with the first expression. For example if you write:

f a b = 2 * a + b

then this is equivalent to:

\a -> (\b -> 2 * a + b)

or less verbose:

\a -> \b -> 2 * a + b
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • An amusing aside: parsing perl actually does depend on the runtime type of the values, making it impossible to statically parse. http://www.jeffreykegler.com/Home/perl-and-undecidability – Carl Jan 06 '19 at 23:25
  • @Carl: ah yes, the article talks about `dunno + 4`. Brilliant :) Thanks for sharing. – Willem Van Onsem Jan 06 '19 at 23:32