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.
Related
So, I have this Haskell question to resolve:
Define a mapIO function that receives a function f and an input and output action a and results in an input and output action that, when executed, performs the given action a and returns the application of f to the return of a.
Here's my code:
mapIO f a = do b <- a
return f(b);
It compiles but it doesn't work. When I try to do the same as the following execution example, it doesn't work. Please, can someone help me?
Prelude Data.Char> mapIO even readLn
75
False
In many other languages, g(x) is the syntax for applying function g to argument x. In Haskell, juxtaposition suffices, so that g x applies g to x. By coincidence, this means g(x) is also valid syntax that applies g to the value (x), which is the same as x, so to a beginner it may seem that g(x) is the correct syntax for function application. But it ain't, and that confusion has bitten you here.
When you write return f(b), you probably assume this means to use the special syntax return and the thing to return should be the function application f(b). However, return is itself a function in Haskell. So what it actually means is to apply return to the function f, then apply the result to the term (b). (Function application is "left-associative" in that sense.)
Luckily the fix for function application associativity problems, as with other associativity problems, is to use parentheses. So:
return (f(b))
Or, without the coincidentally correct extra parentheses:
return (f b)
This leaves only the question of why it "worked" (in the sense of compiled and type-checked) in return f(b) form. This is a bit of an advanced topic; but it turns out that functions also form a Monad with return = const, and so return f(b) actually meant const f(b), which threw away the (b) term. (Aside: in addition to being allowed to use the function instance of Monad, we also must be using the function instance of Monad here. Since we are applying return f to (b), the type of return f must be a function.) So your definition was the same as:
mapIO' f a = do b <- a
f
That is: first do a, throw away its result, then do f as if it were another input/output action. If you check the type inferred for mapIO you will see it matches this intuition:
mapIO :: Monad m => m b -> m t -> m b
Whoops!
I'm having some trouble defining a function in Frege that uses multiple patterns. Basically, I'm defining a mapping by iterating through a list of tuples. I've simplified it down to the following:
foo :: a -> [(a, b)] -> b
foo _ [] = [] --nothing found
foo bar (baz, zab):foobar
| bar == baz = zab
| otherwise = foo bar foobar
I get the following error:
E morse.fr:3: redefinition of `foo` introduced line 2
I've seen other examples like this that do use multiple patterns in a function definition, so I don't know what I'm doing wrong. Why am I getting an error here? I'm new to Frege (and new to Haskell), so there may be something simple I'm missing, but I really don't think this should be a problem.
I'm compiling with version 3.24-7.100.
This is a pure syntactical problem that affects newcomers to languages of the Haskell family. It won't take too long until you internalize the rule that function application has higher precedence than infix expression.
This has consequences:
Complex arguments of function application need parentheses.
In infix expressions, function applications on either side of the operator do not need parentheses (however, individual components of function application may still need them).
In Frege, in addition, the following rule holds:
The syntax of function application and infix expressions on the left hand side of a definition is identical to the one on the right hand side as far as lexemes allowed on both sides are concerned. (This holds in Haskell only when # and ~ are not used.)
This is so you can define an addition function like this:
data Number = Z | Succ Number
a + Z = a
a + Succ b = Succ a + b
Hence, when you apply this to your example, you see that syntactically, you're going to redefine the : operator. To achieve what you want, you need to write it thus:
foo bar ((baz, zab):foobar) = ....
-- ^ ^
This corresponds to the situation where you apply foo to a list you are constructing:
foo 42 (x:xs)
When you write
foo 42 x:xs
this means
(foo 42 x):xs
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?
I have been wondering about this a lot, but I haven't been able to find anything about it.
When using the seq function, how does it then really work? Everywhere, it is just explained saying that seq a b evaluates a, discards the result and returns b.
But what does that really mean? Would the following result in strict evaluation:
foo s t = seq q (bar q t) where
q = s*t
What I mean is, is q strictly evaluated before being used in bar? And would the following be equivalent:
foo s t = seq (s*t) (bar (s*t) t)
I find it a little hard getting specifics on the functionality of this function.
You're not alone. seq is probably one of the most difficult Haskell functions to use properly, for a few different reasons. In your first example:
foo s t = seq q (bar q t) where
q = s*t
q is evaluated before bar q t is evaluated. If bar q t is never evaluated, q won't be either. So if you have
main = do
let val = foo 10 20
return ()
as val is never used, it won't be evaluated. So q won't be evaluated either. If you instead have
main = print (foo 10 20)
the result of foo 10 20 is evaluated (by print), so within foo q is evaluated before the result of bar.
This is also why this doesn't work:
myseq x = seq x x
Semantically, this means the first x will be evaluated before the second x is evaluated. But if the second x is never evaluated, the first one doesn't need to be either. So seq x x is exactly equivalent to x.
Your second example may or may not be the same thing. Here, the expression s*t will be evaluated before bar's output, but it may not be the same s*t as the first parameter to bar. If the compiler performs common sub-expression elimination, it may common-up the two identical expressions. GHC can be fairly conservative about where it does CSE though, so you can't rely on this. If I define bar q t = q*t it does perform the CSE and evaluate s*t before using that value in bar. It may not do so for more complex expressions.
You might also want to know what is meant by strict evaluation. seq evaluates the first argument to weak head normal form (WHNF), which for data types means unpacking the outermost constructor. Consider this:
baz xs y = seq xs (map (*y) xs)
xs must be a list, because of map. When seq evaluates it, it will essentially transform the code into
case xs of
[] -> map (*y) xs
(_:_) -> map (*y) xs
This means it will determine if the list is empty or not, then return the second argument. Note that none of the list values are evaluated. So you can do this:
Prelude> seq [undefined] 4
4
but not this
Prelude> seq undefined 5
*** Exception: Prelude.undefined
Whatever data type you use for seqs first argument, evaluating to WHNF will go far enough to figure out the constructor and no further. Unless the data type has components that are marked as strict with a bang pattern. Then all the strict fields will also be evaluated to WHNF.
Edit: (thanks to Daniel Wagner for suggestion in comments)
For functions, seq will evaluate the expression until the function "has a lambda showing", which means that it's ready for application. Here are some examples that might demonstrate what this means:
-- ok, lambda is outermost
Prelude> seq (\x -> undefined) 'a'
'a'
-- not ok. Because of the inner seq, `undefined` must be evaluated before
-- the lambda is showing
Prelude> seq (seq undefined (\x -> x)) 'b'
*** Exception: Prelude.undefined
If you think of a lambda binding as a (built-in) data constructor, seq on functions is perfectly consistent with using it on data.
Also, "lambda binding" subsumes all types of function definitions, whether defined by lambda notation or as a normal function.
The Controversy section of the HaskellWiki's seq page has a little about some of the consequences of seq in relation to functions.
You can think of seq as:
seq a b = case a of
_ -> b
This will evaluate a to head-normal form (WHNF) and then continue with evaluating b.
Edit after augustss comment: this case ... of is the strict, GHC Core one, which always forces its argument.
I have to dessignate types of 2 functions(without using compiler :t) i just dont know how soudl i read these functions to make correct steps.
f x = map -1 x
f x = map (-1) x
Well i'm a bit confuse how it will be parsed
Function application, or "the empty space operator" has higher precedence than any operator symbol, so the first line parses as f x = map - (1 x), which will most likely1 be a type error.
The other example is parenthesized the way it looks, but note that (-1) desugars as negate 1. This is an exception from the normal rule, where operator sections like (+1) desugar as (\x -> x + 1), so this will also likely1 be a type error since map expects a function, not a number, as its first argument.
1 I say likely because it is technically possible to provide Num instances for functions which may allow this to type check.
For questions like this, the definitive answer is to check the Haskell Report. The relevant syntax hasn't changed from Haskell 98.
In particular, check the section on "Expressions". That should explain how expressions are parsed, operator precedence, and the like.
These functions do not have types, because they do not type check (you will get ridiculous type class constraints). To figure out why, you need to know that (-1) has type Num n => n, and you need to read up on how a - is interpreted with or without parens before it.
The following function is the "correct" version of your function:
f x = map (subtract 1) x
You should be able to figure out the type of this function, if I say that:
subtract 1 :: Num n => n -> n
map :: (a -> b) -> [a] -> [b]
well i did it by my self :P
(map) - (1 x)
(-)::Num a => a->a->->a
1::Num b=> b
x::e
map::(c->d)->[c]->[d]
map::a
a\(c->d)->[c]->[d]
(1 x)::a
1::e->a
f::(Num ((c->d)->[c]->[d]),Num (e->(c->d)->[c]->[d])) => e->(c->d)->[c]->[d]