Haskell: get a prefix operator that works without parentheses

One big argument of prefix operators is good because they can avoid the need for parentheses, so + - 10 1 2 definitely means (10 - 1) + 2 . An infix instance becomes ambiguous if the parens are discarded, that you can end it with certain priority rules, but it's dirty, blah, blah, blah.

I would like to use Haskell to use prefix operations, but the only way I have seen such transactions is to succeed by getting rid of parentheses.

 Prelude> (-) 10 1 

uses two parens.

When you try to create functions, it gets worse because

 Prelude> (+) (-) 10 1 2 

gives an error, I believe, because it tries to feed the minus operation in the plus operation, and not first evaluate the minus and then feed it - so now you need even more parens!

Is there a way to make Haskell intelligently evaluate prefix notation? I think if I made functions like

 Prelude> let pxy = x+y Prelude> let mxy = xy 

I would restore the original winnings compared to fewer parsers, but the composition of the functions would still be a problem. If there is a smart way to join this with the $ notation to make it behave at least close to the way I want, I don't see it. If there was a completely different strategy, I would appreciate hearing it.

I tried to reproduce what accepted the accepted answer:

Haskell: getting rid of parentheses in liftM2

but in both the Prelude console and the Haskell script, the import command does not work. And besides, this is a more advanced Haskell than I can understand, so I was hoping there might be some other simpler solution anyway before I make a hard climb to explore everything that does it.

+5
source share
1 answer

When you try to create functions, it gets worse because

 Prelude> (+) (-) 10 1 2 

gives an error, I believe, because it's trying to feed the minus operation in the operation plus than to evaluate the minus first and then feed it - so now you need even more parens!

This is where you raise exactly the key issue that blocks getting what you want in Haskell.

The designation of the prefix you are talking about is unambiguous for basic arithmetic operations (in general, for any set of functions of statically known arity). But you should know that + and - take two arguments for + - 10 1 2 for unambiguous resolution as +(-(10, 1), 2) (where I have explicit lists of arguments to indicate each call).

But ignoring the specific meaning of + and - , the first function that takes the second function as an argument is a perfectly reasonable interpretation! For Haskell, instead of arithmetic, we need to support higher-order functions, such as map . You would like not not x to turn into not(not(x)) , but map not x should turn to map(not, x) .

What if I had fgx ? How should this work? I need to know what f and g attached to, so I know if this is an example of type not not x or case like map not x to know how to parse the call structure? Even if I assume that I have all the code available for verification, how should I figure out what is connected if I cannot know what the structure of the call of any expression is?

Ultimately, you need to come up with an ambiguity syntax like map (not) x , wrapping not in parentheses to disable its ability to act as an arity-1 function (just like the actual Haskell syntax, it allows you to disable operators in parentheses for disabling their ability to act as an infix operator). Or use the fact that all Haskell functions are arity-1, but then you need to write (map not) x , and your arithmetic example should look like (+ ((- 10) 1)) 2 . Back to the parentheses!

The truth is that the prefix notation you propose is not unique. Haskell normal function syntax (without operators) - ; rule: you always interpret a sequence of terms like foo bar baz qux etc as ((((foo) bar) baz) qux) etc (where each of foo, bar, etc. can be an identifier or a mixture in parentheses). You use parentheses to not eliminate this rule, but to group terms to impose a different call structure than this heavy rule will give you.

The infix operators complicate this rule, and they are ambiguous, not knowing what the involved operators are (their priority and associativity, which, unlike arity, are associated with a name not referring to the actual value). These complications were added to help make the code more understandable; especially for arithmetic conventions, most programmers are already familiar (which + has a lower priority than * , etc.).

If you do not like the additional burden of remembering the priority and associativity of operators (rather than an unreasonable position), you can use a notation that is unambiguous, without priority rules, but it should be a Haskell prefix , not a Polish prefix notation. And any syntax convention you use, in any language, you should always use something like parentheses to indicate the grouping in which you need a call structure different from what the standard convention indicates. So:

 (+) ((-) 10 1) 2 

Or:

 plus (minus 10 1) 2 

if you define non-operator function names.

+5
source

Source: https://habr.com/ru/post/1264852/


All Articles