Pregunta

I'm writing a custom language that features some functional elements. When I get stuck somewhere I usually check how Haskell does it. This time though, the problem is a bit to complicated for me to think of an example to give to Haskell.

Here's how it goes.

Say we have the following line

a . b

in Haskell. Obviously, we are composing two functions, a and b. But what if the function a took another two functions as parameters. What's stopping it from operating on . and b? You can surround it in brackets but that shouldn't make a difference since the expression still evaluates to a function, a prefix one, and prefix functions have precedence over infix functions.

If you do

(+) 2 3 * 5

for example, it will output 25 instead of 17.

Basically what I'm asking is, what mechanism does Haskell use when you want an infix function to operate before a preceding prefix function.

So. If "a" is a function that takes two functions as its parameters. How do you stop Haskell from interpreting

a . b

as "apply . and b to the function a" and Interpret it as "compose functions a and b".

¿Fue útil?

Solución

If you don't put parens around an operator, it's always parsed as infix; i.e. as an operator, not an operand.
E.g. if you have f g ? i j, there are no parens around ?, so the whole thing is a call to (?) (parsed as (f g) ? (i j), equivalent to (?) (f g) (i j)).

Otros consejos

I think what you're looking for are fixity declarations (see The Haskell Report).

They basically allow you to declare the operator precedence of infix functions.

For instance, there is

infixl 7 *
infixl 6 +

which means that + and * are both left associative infix operators. * has precedence 7 while + has precendence 6, i.e * binds stronger than +. In the report page, you can also see that . is defined as infixr 9 .

Basically what I'm asking is, what mechanism does Haskell use when you want an infix function to operate before a preceding prefix function.

Just to point out a misconception: This is purely a matter of how expressions are parsed. The Haskell compiler does not know (or: does not need to know) if, in

f . g

f, g and (.) are functions, or whatever.

It goes the other way around:

  1. Parser sees f . g (or, the syntactically equivalent: i + j)
  2. Hands this up as something like App (App (.) f) g following the lexical and syntax rules.
  3. Only then, when the typechecker sees App a b it concludes that a must be a function.
(+) 2 3 * 5

is parsed as

((+) 2 3) * 5

and thus

(2 + 3) * 5

That is, because function applications (like (+) 2 3) get evaluated first, before functions in infix notation, like *.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top