function name vs variable in haskell - haskell

From haskell documentation:
Identifiers are lexically distinguished into two namespaces (Section 1.4): those that begin with a lower-case letter (variable
identifiers) and those that begin with an upper-case letter
(constructor identifiers).
So a variable containing a constant value, i.e a=4 and the function name add add a b = a + b are both variable identifiers, true? Can we say that a function name is variable?
From another academic source:
f (patter1)...(pattern2) = expression
..where a pattern can be constructor or a variable, not a defined
function
This is where I get confused. As I can do f g x where g is a function, I again see that a function name is a variable then. True?
What do they mean with "not a defined defined function" then?

A function name can be a variable identifier, except when it is an operator like +.
This is a statement about lexical matters.
You can't infer from that that a function name is a variable. (Because a variable is not a lexical thing.)
It is the other way around, like in
f . g = \a -> f (g a)
where f and g are variables, i.e. names that are bound to some unknown-in-advance values, but we know that those values must be functions.

A named function is indeed just a global variable who's "value" just happens to be a function. For example,
id x = x
can just as well be written as
id = ( \ x -> x )
Haskell explicitly makes no distinction between these two. Even the type signature says it:
id :: x -> x
So id is just a value who's value has type x -> x (i.e., a function).
Somebody else said something about operators not being variables; this is untrue.
let (<+>) = \ x y -> (x+y)/(x*y) in 5 <+> 6
You can even do something utterly horrifying like write a loop where the contents of <+> changes each time through the loop. (But why in the hell would anybody ever do that?)

Related

Express a "case ... of" pattern more elegantly in Haskell

I came across a pattern which I believe can be expressed more elegantly:
I have two functions f1,f2 :: Int -> Int (their impl. is not relevant), and a process :: Int -> Int which does the following:
if f1 x produces x1 different from x, then repeat the process with x1
otherwise, if f2 x produces x2 different from x, then repeat the process with x2
finally, stop the process and return x
My case ... of implementation is the following:
f1 :: Int -> Int
f1 = undefined
f2 :: Int -> Int
f2 = undefined
process :: Int -> Int
process x =
case f1 x of
x ->
case f2 x of
x -> x
x' -> process x'
x' -> process x'
which produces the following warnings:
so.hs:13:17: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
13 | x' -> process x'
| ^^^^^^^^^^^^^^^^
so.hs:14:9: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
14 | x' -> process x'
| ^^^^^^^^^^^^^^^^
Can anyone shed some light as to what patterns are overlapping, and how to implement process more elegantly?
There is no way to write a pattern for "a value equal to the one I have stored in a variable x". This is because pattern matching is the primary way variables are created in Haskell.
process :: Int -> Int
process x =
Here x is a pattern. It's a very simple pattern, since it just matches any possible value for the argument to process, but you could have written a more structured pattern, or even multiple equations for process matching different patterns for that argument. And within the scope of that pattern match (the entire RHS of process), you have x as a local variable referring to the matched value.
case f1 x of
x ->
Here x is once again a pattern, and once again it is a very simple pattern matching any possible value that was inspected by the case expression. Then you have x as a new local variable referring to the matched value within the scope of the match (everything the RHS of the -> arrow); and because you have created two local variables with the same name x, the most local one shadows the other in the scope where they both apply (so you have no way of referring to the original x in the RHS of the -> arrow, only the new x that is the result of f applied to the original x).
If you think the pattern x in the case expression ought to mean "match a value equal to x", then why should the pattern x in the function argument mean "match anything and call it x"? You can't have your cake and eat it too1.
Haskell makes the rule very simple: a variable appearing in a pattern is always the creation of a new variable to refer to the value that matched the pattern. It is never a reference to an existing variable to check if the matched value is equal to it. Only constructors will be "checked to see if they match"; variables are just bound to whatever is there2.
The same applies to your inner case, where you meant to test the result to see if it was still x but actually just created yet another x shadowing both of the outer x variables.
This is why the compiler complains about your other pattern matches being redundant. Pattern are checked in order, and the first pattern in each case already matches anything (and calls it x), so the second match in each case will never even be tried.
So, since pattern matching can never test whether a value is equal to a variable, you just need to use a construct other than pattern matching! if ... then ... else ... would work fine. You could also use a guard on a pattern.
2 At least not if you want to be able to tell what a pattern means locally, without examining all containing scopes including the entire module and all imports. A hypothetical language could decide the meaning of the pattern based on whether there's already a variable of that name in scope, but I think Haskell makes right call here. Unexpected shadowing sometimes causes tricky bugs, but at least some sign of them is always local. It would be a nightmare if you could change a pattern from a catch-all to an equality check by introducing a global scope variable with the same name (possibly not even in the same module or even package!).
2 This is actually the core reason we have the syntactic distinction between constructors starting with a capital letter and variables starting with a lowercase letter! The language designers wanted it to be easy to tell at a glance which words are constructors to be matched and which are variables to be bound, without having to consider all the constructor names in scope.
Following Ben's advice, I wrote the following:
process :: Int -> Int
process x
| x /= x1 = process x1
| x /= x2 = process x2
| otherwise = x
where
x1 = f1 x
x2 = f2 x

How to implement static scope, dynamic scope, and lazy evaluation in ml and haskell?

I understand conceptually what all of these are, I'm just hoping for some code examples of how to implement them in ML and Haskell.
Haskell variables (top level definitions, variables in patterns, etc.) are all statically scoped. For example, the program:
y = "global value"
f = print y
g = let y = "local value" in f
main = g
will print "global value". Even though, in the definition of g, the function f is used after "redefining" y, this redefinition doesn't affect the definition of f which uses the statically (AKA lexically) scoped definition of y in force where f was defined.
If you want to "implement" dynamic scope, you have to be more specific about what you really mean. If you're wondering if you can write a function in plain Haskell, like:
addY :: Int -> Int
addY x = x + y
such that y might refer to a different variable from one call to the next, then the answer is no. In this definition, y always refers to the same variable (which, in Haskell, means the same, immutable value) which can be determined by static analysis of the program and cannot be dynamically redefined.
[[Edit: As #Jon Purdy points out, though, there's a Haskell extension that supports a form of dynamic scope such that the following prints various dynamically scoped local values with the same function.
{-# LANGUAGE ImplicitParams #-}
f :: (?y :: String) => IO ()
f = print ?y
g = let ?y = "g's local value" in f
h = let ?y = "h's local value" in f
main = do
g -- prints g's local value
h -- prints h's local value
let ?y = "main's local value" in f -- prints main's value
--end of edit--]]
For lazy evaluation, there are many examples, such as the following entered into an interactive GHCi session:
take 3 [1,2..] -- gives [1,2,3]
let x = (15^2, 6 `div` 0)
fst x -- gives 225
let y = snd x
y -- *** Exception: divide by zero
In the first line, if the evaluation was strict, the attempt to fully evaluate the infinite list [1,2..] (can also be written [1..] -- just counts up 1,2,3,.. forever) would go into an infinite loop, and the take function would never be called. In the second example, if evaluation was strict, the division by zero error would occur when x was defined, not only after we tried to print its second component.

Operator as an argument in Haskell

I'm quite new to Haskell, may be it's a stupid question.
What I want is to give to my function as an argument any operator.
For example:
myFunc :: a -> Int -> Int -> Boolean
myFunc operator a b = a operator b
*Project> myFunc (>) 5 2
True
*Project> myFunc (<=) 5 2
False
Help me in advice how to do that please!
You can do that with haskell function arguments.
In your function above, you want myFunc to take a function that takes two Ints and returns a Bool (not a Boolean, you must have typed that wrong). The declaration for that function would be (Int -> Int -> Bool). Therefore, you can write:
myFunc :: (Int -> Int -> Bool) -> Int -> Int -> Bool
myFunc op a b = a `op` b
This defines a higher-order function that takes a function with two Int parameters that returns a Bool (and two Ints). You can now use it like any other function parameter!
Note that this is exactly the same as doing:
myFunc (#) a b = a # b
Or:
myFunc (%) a b = a % b
Because using infix operaters like * or /, or any operator composed only of special characters, without backticks is just shorthand for using them with (typing `/` every time you want to divide something would get annoying!).
Under the hood, functions "exist" without names. Any function you define (or that is already defined in libraries), such as myFunc just is a function value, and the name just gives us a way to refer to it in other code that wants to use it. This is exactly the same as if you write x = 3: the value 3 "exists" independently of the name x, that name just gives us a way to refer to it.
Why is this relevant to your question about passing operators?
Well, as far as Haskell is concerned, operators like > and <= are also just nameless functions that happen to be bound to the names > and <=. The special treatment of them as operators (that you can write them infix between the arguments you're calling them on) is only about the names, and changes if you refer to them with different names.
There are two types of names in Haskell. Alphanumeric names (consisting only of letters, numbers, and underscores), and symbolic names (consisting only of symbol characters). If you have an expression {1} {2} {3}, then if {2} is a symbolic name (and {1} and {3} aren't symbolic names; otherwise you have a syntax error), then the expression is interpreted as meaning "call {2} on the arguments {1} and {3}". But if none of them are symbolic names, then it's instead interpreted as "call {1} on the arguments {2} and {3}".1
But all of this happens only with reference to the name, not to the functions actually referred to by those names. So if you write your myFunc like so:
myFunc operator a b = operator a b
Then it doesn't actually matter whether myFunc was called like myFunc (+) 1 2 or like myFunc plus 1 2; inside the definition of myFunc the "operator" is referred to by the name operator, which is an alphanumeric name. So you put it first when you want to call it, with its arguments following.
Alternatively you could use a symbolic name inside myFunc, like so:
myFunc ($&^*) a b = a $&^* b
Again, this also works even when myFunc was called with a non-operator function like myFunc plus 1 2.
And of course, there are ways to convert either kind of name to work like the other; you can put an alphanumeric name in backticks to use it infix like an operator:
myFunc operator a b = a `operator` b
And you can put a symbolic name in parentheses to simply use it as reference to the function it's bound to (and this is in fact the only way to use an operator without providing arguments for it):
myFunc ($^&*) a b = ($&^*) a b
So basically, the only special thing you needed to know to pass an operator to your function is what you already knew: put the operator in parentheses when you call the function. Inside the definition of the function, you can write it exactly the same as any other function; the style of name you choose in that function definition will determine whether you call it like an operator or like an ordinary function. You don't need to know (and in fact cannot find out) whether it was an operator "outside" the function.
1 Of course, when you have more complex expressions involving more than 3 things and multiple operators, then the rules of precedence and associativity come into play to determine exactly what's going on.

How are point-free functions actually "functions"?

Conal here argues that nullary-constructed types are not functions. However, point-free functions are described as such for example on Wikipedia, when they take no explicit arguments in their definitions, and it seemingly is rather a property of currying. How exactly are they functions?
Specifically: how are f = map and f = id . map different in this context? As in, f = map is simply just a binding to a value that happens to be a function where f simply "returns" map (similar to how f = 2 "returns" 2) which then takes the arguments. But f = id . map is referred to as a function because it's point-free.
Conal's blog post boils down to saying "non-functions are not functions", e.g. False is not a function. This is pretty obvious; if you consider all possible values and remove the ones which have a function type, then those that remain are... not functions.
That has absolutely nothing to do with the notion of point-free definitions.
Consider the following function definitions:
map1, map2, map3, map4 :: (a -> b) -> [a] -> [b]
map1 = map
map2 = id . map
map3 f = map f
map4 _ [] = []
map4 f (x:xs) = f x : map4 f xs
These are all definitions of the same function (and there are infinitely many more ways to define something equivalent to the map function). map1 is obviously a point-free definition; map4 is obviously not. They also both obviously have a function type (the same one!), so how can we say that point-free definitions are not functions? Only if we change our definition of "function" to something else than what is usually meant by Haskell programmers (which is that a function is something of type x -> y, for some x and y; in this case we're using a -> b as x and [a] -> [b] for y).
And the definition of map3 is "partially point-free" (point-reduced?); the definition names its first argument f, but doesn't mention the second argument.
The point in all this is that "point-free-ness" is a quality of definitions, while "being a function" is a property of values. The notion of point-free function doesn't actually make sense, since a given function can be defined many ways (some of them point-free, others not). Whenever you see someone talking about a point-free function, they mean a point-free definition.
You seem to be concerned that map1 = map isn't a function because it's just a binding to the existing value map, just like x = 2. You're confusing notions here. Remember that functions are first-class in Haskell; "things that are functions" is a subset of "things that are values", not a different class of thing! So when map is an existing value which is a function, then yes map1 = map is just binding a new name to an existing value. It's also defining the function map1; the two are not mutually exclusive.
You answer the question "is this point-free" by looking at code; the definition of a function. You answer the question "is this a function" by looking at types.
Contrary to what some people might believe everything in Haskell is not a function. Seriously. Numbers, strings, booleans, etc. are not functions. Not even nullary functions.
Nullary Functions
A nullary function is a function which takes no arguments and performs some “side-effectful” computation. For example, consider this nullary JavaScript function:
main();
function main() {
alert("Hello World!");
alert("My name is Aadit M Shah.");
}
Functions that take no arguments can only return different results if the are side-effectful. Thus, they are similar to IO actions in Haskell which take no arguments and perform some side-effectful computations:
main = do
putStrLn "Hello World!"
putStrLn "My name is Aadit M Shah."
Unary Functions
In contrast, functions in Haskell can never be nullary. In fact, functions in Haskell are always unary. Functions in Haskell always take one and only one argument. Multiparameter functions in Haskell can be simulated either using currying or using data structures with multiple fields.
add' :: Int -> Int -> Int -- an example of using currying
add' x y = x + y
add'' :: (Int, Int) -> Int -- an example of using multi-field data structures
add'' (x, y) = x + y
Covariance and Contravariance
Functions in Haskell are a data type, just like any other data type you may define in Haskell. However, functions are special because they are contravariant in the argument type and covariant in the return type.
When you define a new algebraic data type, all the fields of its type constructors are covariant (i.e. a source of data) instead of contravariant (i.e. a sink of data). A covariant field produces data while a contravariant field consumes data.
For example, suppose I create a new data type:
data Foo = Bar { field1 :: Char, field2 :: Int }
| Baz { field3 :: Bool }
Here the fields field1, field2 and field3 are covariant. They produce data of the type Char, Int and Bool respectively. Consider:
let x = Baz True -- I create a new value of type Foo
in field3 x -- I can access the value of field3 because it is covariant
Now, consider the definition of a function:
data Function a b = Function { domain :: a -- the argument type
, codomain :: b -- the return type
}
Ofcourse, a function is not actually defined as follows but let's assume that it is. A function has two fields domain and codomain. When we create a value of the type Function we don't know either of these two fields.
We don't know the value of domain because it is contravariant. Hence, it needs to be provided by the user.
We don't know the value of codomain because although it is covariant yet it might depend on the domain and we don't know the value of the domain.
For example, \x -> x + x is a function where the value of the domain is x and the value of the codomain is x + x. Here the domain is contravariant (i.e. a sink of data) because data goes into the function via the domain. Similarly, the codomain is covariant (i.e. a source of data) because data comes out of the function via the codomain.
The fields of algebraic data structures in Haskell (like the Foo we defined earlier) are all covariant because data comes out of those data structures via their fields. Data never goes into these structures like the way it does for the domain field of functions. Hence, they are never contravariant.
Multiparameter Functions
As I explained before, although all functions in Haskell are unary yet we can emulate multiparameter functions either using currying or fields with multiple data structures.
To understand this, I'll use a new notation. The minus sign ([-]) represents a contravariant type. The plus sign ([+]) represents a covariant type. Hence, a function from one type to another is denoted as:
[-] -> [+]
Now, the domain and the codomain of the function could each be individually replaced with other types. For example in currying, the codomain of the function is another function:
[-] -> ([-] -> [+]) -- an example of currying
Notice that when a covariant type is replaced with another type then the variance of the new type is preserved. This makes sense because this is equivalent to a function with two arguments and one return type.
On the other hand if we were to replace the domain with another function:
([+] -> [-]) -> [+]
Notice that when we replace a contravariant type with another type then the variance of the new type is flipped. This makes sense because although ([+] -> [-]) as a whole is contravariant yet its input type becomes the output of the whole function and its output type becomes the input of the whole function. For example:
function f(g) { // g is contravariant for f (an input value for f)
return g(x) + 10; // x is covariant for f (an output value for f)
// x is contravariant for g (an input value for g)
// g(x) is contravariant for f (an input value for f)
// g(x) is covariant for g (an output value for g)
// g(x) + 10 is covariant for f (an output value for f)
}
Currying emulates multiparameter functions because when one function returns another function we get multiple inputs and one output because variance is preserved for the return type:
[-] -> [-] -> [+] -- a binary function
[-] -> [-] -> [-] -> [+] -- a ternary function
A data structure with multiple fields as the domain of a function also emulates multiparameter functions because variance is flipped for the argument type of a function:
([+], [+]) -- the fields of a tuple are covariant
([-], [-]) -> [+] -- a binary function, variance is flipped for arguments
Non Functions
Now, if you take a look at values like numbers, strings and booleans, these values are not functions. However, they are still covariant.
For example, 5 produces a value of 5 itself. Similarly, Just 5 produces a value of Just 5 and fromJust (Just 5) produces a value of 5. None of these expressions consume a value and hence none of them are contravariant. However, in Just 5 the function Just consumes the value 5 and in fromJust (Just 5) the function fromJust consumes the value Just 5.
So everything in Haskell is covariant except for the arguments of functions (which are contravariant). This is important because every expression in Haskell must evaluate to a value (i.e. produce a value, not consume a value). At the same time we want functions to consume a value and produce a new value (hence facilitating transformation of data, beta reduction).
The end effect is that we can never have a contravariant expression. For example, the expression Just is covariant and the expression Just 5 is also covariant. However, in the expression Just 5 the function Just consumes the value 5. Hence, contravariance is restricted to function arguments and bounded by the scope of the function.
Because every expression in Haskell is covariant people often think of non-functional values like 5 as “nullary functions”. Although this intuition is insightful yet it is wrong. The value 5 is not a nullary function. It is an expression which is cannot be beta reduced. Similarly, the value fromJust (Just 5) is not a nullary function. It is an expression which can be beta reduced to 5, which is not a function.
However, the expression fromJust (Just (\x -> x + x)) is a function because it can be beta reduced to \x -> x + x which is a function.
Pointful and Pointfree Functions
Now, consider the function \x -> x + x. This is a pointful function because we are explicitly declaring the argument of the function by giving it the name x.
Every function can also be written in pointfree style (i.e. without explicitly declaring the argument of the function). For example, the function \x -> x + x can be written in pointfree style as join (+) as described in the following answer.
Note that join (+) is a function because it beta reduces to the function \x -> x + x. It doesn't look like a function because it has no points (i.e. explicitly declared arguments). However, it is still a function.
Pointfree functions have nothing to do with currying. Pointfree functions are about writing functions without points (e.g. join (+) instead of \x -> x + x). Currying is when one function returns another function, thereby allowing partial application (e.g. \x -> \y -> x + y which can be written in pointfree style as (+)).
Name Binding
In the binding f = map we are just giving map the alternative name f. Note that f does not “return” map. It is just an alternative name for map. For example, in the binding x = 5 we don't say that x returns 5 because it doesn't. The name x is not a function nor a value. It's just a name which identifies the value of 5. Similarly, in f = map the name f just identifies the value of map. The name f is said to denote a function because map denotes a function.
The binding f = map is pointfree because we haven't explicitly declared any arguments of f. If we wanted to then we could have written f g xs = map g xs. This would be a pointful definition but because of eta conversion we can write it more succinctly in pointfree form as f = map. The concept of eta conversion is that \x -> f x is equivalent to f itself and that the pointful \x -> f x can be converted into the pointfree f and vice versa. Note that f g xs = map g xs is just syntactic sugar for f = \g xs -> map g xs.
On the other hand f = id . map is a function not because it is pointfree but because id . map beta reduces to the function \x -> id (map x). BTW, any function composed with id is equivalent to itself (i.e. id . f = f . id = f). Hence, id . map is equivalent to map itself. There's no difference between f = map and f = id . map.
Just remember that f is not a function that “returns” id . map. It is just a name given to the expression id . map for convenience.
P.S. For an intro to pointfree functions read:
What does (f .) . g mean in Haskell?

function parameters in haskell

I can use parenthesis to make cons operator have more priority than function application in this patter match equation:
tail (_:xs) = xs
However it will be "parse error in pattern" if I try to write this:
f (g x) = 7
I see that g x produces a value and we should directly pass that value. Or in this way f g x = g x + 7 we make a call to g with an argument x in the body of f definition.
But what is the reason for not allowing to pass a function call in the pattern?
A pattern match is about destructuring things. Think along the lines of "I have build this data using constructor A". With pattern matching we could see what values we supplied A.
This means that means that constructors have to be invertible, we need to be able to figure out a constructors inputs given the results. Now if you wanted to do the same thing with a function call you'd be in trouble since you can't just invert a function, imagine f = const 0.
What it sounds like you want instead is a view pattern. This is where you are passed data, feed it into a function, and then pattern match on the result.
{-# LANGUAGE ViewPatterns #-}
foo (bar -> Just a) = a
This should be read as "Feed the argument to bar, then pattern match on the resulting Maybe".
We don't pass anything in a pattern. We describe how data that is passed must look like for the corresponding equation to take effect.
Now, it turns out that every value is of the form g x for some combination of g and x, so the pattern g x can be abbreviated to just x.

Resources