What is the difference between an operator and a function in Haskell? - haskell

I am new to Haskell and this mixture of Infix and Prefix notation is confusing me.
What is the difference between an operator like '+' and a function like head? How do I write an operator 'c' which does this 1 c 1 = 2?
I found this definition a ! b = True. How does Haskell know that I am defining ! and not a function a?

In Haskell, to create an operator you must use the following "operator symbols":
! # $ % * + . / < = > ? \ ^ | : - ~
So, for example
($$$) a b = a+b
Defines an operator $$$ which can be used in the expression 1 $$$ 1 to yield a value of 2.
Conceptually, there is no difference between an operator and a function, and you can use backticks or parens to make one work like the other.
EDIT:
Just so it is 100% clear, let me demonstrate turning a function into an operator and vice versa:
For the operator '+', the following two expressions are equivalent:
1+1
(+) 1 1
Similarly, for a function, the following two expressions are equivalent:
foo 1 2
1 `foo` 2

Haskell knows you aren't defining a function called a because the ! wouldn't be valid in a function argument list. In order to use the ! not as an operator but just as a normal identifier, you need to enclose it in parentheses. If you wrote instead a (!) b = True, then it would define the function a :: t -> t1 -> Bool.
This is the entire difference between operators and normal identifiers in Haskell — there are special syntax rules for operators that allow them to be used infix without backticks. Otherwise, they're just functions.

Really, the only difference is syntax. Function names begin with a lower-case letter, followed by a series of alpha-numeric characters. Operators are some unique sequence of the typical operator characters (+ - / * < > etc.).
Functions can be used as operators (in-fix) by enclosing the function name in ` characters. For example:
b = x `elem` xs -- b is True if x is an element in xs.
Operators can be used as functions (pre-fix) by enclosing the operator in parens. For example:
n = (+) 2 5 -- n = 2 + 5, or 7.

Related

pattern matching of negative literals in Haskell

I was trying to understand why n + k patterns were banned in Haskell. A famous post on StackOverflow gives an example of a function as follows:
f 0 = 0
f (n + 5) = 5
Haskell shows an error while matching f 1, f 2, f 3, f 4.
I cannot understand why (-1) cannot be matched with n. Firstly, I thought that integers only contain non-negative literals (0,1,..), but Haskell's definition of Int type includes negative literals.
Why can't -1 be matched? That's simply how n+k patterns were defined, presumably because it seemed like a good idea at the time. It's natural to use induction for natural numbers, so why not define our cool n+k patterns to work for naturals? From the Haskell report:
Matching an n+k pattern (where n is a variable and k is a positive integer literal) against a value v succeeds if x >= k, resulting in the binding of n to x - k, and fails otherwise. Again, the functions >= and - are overloaded, depending on the type of the pattern. The match diverges if the comparison diverges.
The fact that you found this surprising is probably one reason why n+k patterns were removed. Another is that there's no need for them: you can easily translate any n+k pattern into a pattern not using this feature.

Partial Function Application in Concatenative Programming Languages

Say I have a haskell function f n l = filter (n<) l where it takes an integer n and list l and returns all of the integers in l greater then n.
I'm trying to figure out how to best write this function in a language like Joy. I've generally had good luck with converting the haskell function to pointfree form f = filter . (<) and then trying to rewrite it in Joy from there. But I can't figure out how to simulate partial function application in a concatenative language.
So far, I've tried to do something like swap [[>] dip] filter, but it seems like there must be a better/cleaner way to write this.
Also, I'm experimenting with writing my own concatenative language and was wondering if lazy-evaluation could be compatible with concatenative languages.
swap [[>] dip] filter won’t work because it assumes n is accessible for each call to the quotation by which you’re filtering; that implies filter can’t leave any intermediate values on the stack while it’s operating, and > doesn’t consume n. You need to capture the value of n in that quotation.
First “eta”-reduce the list parameter:
l n f = l [ n > ] filter
n f = [ n > ] filter
Then capture n by explicitly quoting it and composing it with >:
n f = n quote [ > ] compose filter
(Assuming quote : a -> (-> a) a.k.a. unit, takes a value and wraps it in a quotation and compose : (A -> B) (B -> C) -> (A -> C) a.k.a. cat, concatenates two quotations.)
Then just “eta”-reduce n:
f = quote [ > ] compose filter
I put “eta” in scare quotes because it’s a little more general than in lambda calculus, working for any number of values on the stack, not just one.
You can of course factor out partial application into its own definition, e.g. the papply combinator in Cat, which is already defined as swons (swap cons) in Joy, but can also be defined like so:
DEFINE
papply (* x [F] -- [x F] *)
== [unit] dip concat ;
f (* xs n -- xs[>=n] *)
== [>] papply filter .
In Kitten this could be written in a few different ways, according to preference:
// Point-free
function \> compose filter
// Local variable and postfix
-> n; { n (>) } filter
// Local variable and operator section
-> n; \(n <) filter
Any evaluation strategy compatible with functional programming is also compatible with concatenative programming—popr is a lazy concatenative language.

Fixity of infix value constructors

Let:
data Some a b = Some a b deriving (Show)
Then (in ghci):
> Some (id 1) (id 2)
Some 1 2
But (not surprisingly):
> Some id 1 id 2
Couldn't match expected type ‘(a1 -> a1) -> Integer -> t’ ...
However:
> id 1 `Some` id 2
Some 1 2
Why is that? Does fixity of infix value constructors defaults to the lowest?
A constructor is a function as well: we can use a constructor C as a function that takes the parameters the constructor is going to hold as arguments, and then constructs a new instance of the type. So in your example, Haskell syntactically sees Some like it sees any function.
If you write a function between backquotes (`), then it acts like an operator, like it is written in Section 3 of the Haskell '98 report:
An operator is either an operator symbol, such as + or $$, or is an ordinary identifier enclosed in grave accents (backquotes), such as `op`. For example, instead of writing the prefix application op x y, one can write the infix application x `op` y. If no fixity declaration is given for `op` then it defaults to highest precedence and left associativity.
The section also describes that function application has priority over operators. We see that an expression exp can be a fexp (an function application expression). The arguments of such function application are aexps. An aexp can contain an operator (through exp), but only in case it is between brackets (()), square brackets ([], when we construct a list), etc. But not without a specification of priority. If we write: f a b + g x a, it is thus interpreted as (f a b) + (g x y), not as f a (b+g) x y.
Now the only question that is still open is what happens in case the expression contains other operators. In Haskell we assign precedence (and associativty) to operators. This is described in Section 4 of the Haskell '98 report. All operators are assigned a precedence between 0 and 9. The * operator has for instance higher precedence than +, and that means that 2 + 3 * 2 is interpreted as 2 + (3 * 2), and not as (2 + 3) * 2. As is described in the quoted section, if you do not specify the precedence, then it is the highest. So 1 + id 2Someid 3 * 5 is interpreted as 1 + (((id 2) `Some` (id 3)) * 5) (but this makes no sense here, since we can not multiply a Some object with 5.
So your expression:
id 1 `Some` id 2
is equivalent to:
Some (id 1) (id 2)

Can | be used as part of variable name?

This code causes compiler error :
Prelude> let probBorA = 3
probBorA :: Num a => a
Prelude> let probB|A = 3
<interactive>:25:11: Not in scope: data constructor ‘A’
Prelude>
| cannot be used as part of a variable name in Haskell ?
It cannot be part of a name that contains alphanumeric characters, as in your example. Names of bindings that are not infix operators must contain only alphanumeric characters, single quotes and underscores. There are further restrictions on what may start with an uppercase letter or lowercase letter and a couple minor restrictions on where single quotes can appear. A name can also not start with a number.
The particular character | has special meaning because it is the syntax for guards. Your example would be the same as:
Prelude> let prob | A = 3
For more details, see the link Eric provided in the comments.
camelCase is the recommended (and, by a very large margin, the most prevalent) naming convention, but you could also name things like_this or even'like'this.
The ' (single quote) is most often used at the end of a variable name, usually to indicate that it is a modified version of the binding without the single quote. For instance, you might have
ghci> :{
|> let x = 3
|> x' = x + 1
|> x'' = x' * 2
|> in (x, x', x'')
|> :}
(3,4,8)
It is possible to make new operators (with new names) in Haskell like this:
ghci> let a .|. b = a + b
ghci> 2 .|. 2
4
Or even, if you really wanted to:
ghci> let a !##$%^&* b = a - b
ghci> 7 !##$%^&* 4
3
(Usually you try to use operator names that are far more clear though)
but, as I said, | by itself has special significance.

What do the parentheses signify in (x:xs) when pattern matching?

when you split a list using x:xs syntax why is it wrapped in a parentheses? what is the significance of the parentheses? why not [x:xs] or just x:xs?
The cons cell doesn't have to be parenthesized in every context, but in most contexts it is because
Function application binds tighter than any infix operator.
Burn this into your brain in letters of fire.
Example:
length [] = 0
length (x:xs) = 1 + length xs
If parentheses were omitted the compiler would think you had an argument x followed by an ill-placed infix operator, and it would complain bitterly. On the other hand this is OK
length l = case l of [] -> 0
x:xs -> 1 + length xs
In this case neither x nor xs can possibly be construed as part of a function application so no parentheses are needed.
Note that the same wonderful rule function application binds tighter than any infix operator is what allows us to write length xs in 1 + length xs without any parentheses. The infix rule giveth and the infix rule taketh away.
You're simply using the cons operator :, which has low precedence. Parentheses are needed so that things stay right.
And you don't use [x:xs], because that would match a list whose only element is a list with head x and tail xs.
I don't know exact answer, but I guess that is due to what can be matched in patterns. Only constructors can be matched. Constructors can be of single word or composite. Look at the next code:
data Foo = Bar | Baz Int
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
Single word constructors match as is. But composite constructors must be surrounded with parens in order to avoid ambiguity. If we skip parens it looks like matching against two independent arguments:
f Baz x = x - 1
So, as (:) is composite it must be in parens. Skipping parens for Bar is a kind of syntactic sugar.
UPDATE: I realized that (as sykora noted) it is a consequence of operator precedence. It clarifies my assumptions. Function application (which is just space between function and argument) has highest precedence. Others including (:) have lower precedence. So f x:xs is to be interpreted as ((:) (f x)) xs that is presumably not what we need. While f (x:xs) is interpreted as f applied to x:xs which is in turn (:) applied to x and xs.
It's to do with parsing.
Remember, the colon : is just a constructor that's written with operator syntax. So a function like
foo [] = 0
foo (x:xs) = x + foo xs
could also be written as
foo [] = 0
foo ((:) x xs) = x + foo xs
If you drop the parenthesis in that last line, it becomes very hard to parse!
: is a data constructor, like any other pattern match, but written infix. The parentheses are purely there because of infix precedence; they're actually not required and can be safely omitted when precedence rules allow. For instance:
> let (_, a:_) = (1, [2, 3, 4]) in a
2
> let a:_ = "xyzzy"
'x'
> case [1, 2, 3] of; a:b -> a; otherwise -> 0;
1
Interestingly, that doesn't seem to work in the head of a lambda. Not sure why.
As always, the "juxtaposition" operator binds tighter than anything else, so more often than not the delimiters are necessary, but they're not actually part of the pattern match--otherwise you wouldn't be able to use patterns like (x:y:zs) instead of (x:(y:zs)).

Resources