substitute':: (Eq a)=> a -> a -> [a] -> [a]
substitute' x y = map substituteOne
where
substituteOne x' | x == x' = y
| otherwise = x'
So, the point of this function is, that it takes two inputs of type a and a list of type a and substitutes all elements in list [a] that are from the "first" a with the "second" a. At least that is what the task description says.
I already implemented a recursive version, but a function with a where clause is also needed.
So THAT is the solution for it. Somehow I have questions:
how can substituteOne in the second line work without any parameters?
where do we give a list as input? or where do we state WHAT we do with that list? I mean compiling and eecuting it works, but somehow I don't see it
what is x' ? it is never defined anywhere, we just start working with it somehow (maybe refers also to question 1)
map needs a function and a list, so that it works. here we have map function _. refers maybe to 2., but what would be the output of substituteOne x' ?
If needed, result looks like this:
substitute' 5 10 [1, 5, 2, 5, 3, 5]
[1,10,2,10,3,10]
(1) how can substituteOne in the second line work without any parameters?
(2) where do we give a list as input? or where do we state what we do with that list? I mean compiling and executing it works, but somehow I don’t see it
The parameters are still there; this is currying at work. Consider the section of an infix operator (+1), which is a special case of partial application. Given a number, it produces a number that is one greater. Witness:
λ> :t (+1)
(+1) :: Num a => a -> a
We could define a function to increment all elements of a list by naming the list
λ> :t \l -> map (+1) l
\l -> map (+1) l :: Num b => [b] -> [b]
but that turns out to be unnecessary because of currying.
λ> :t map (+1)
map (+1) :: Num b => [b] -> [b]
This is functional programming, after all. With Haskell, we manipulate functions as easily as other languages manipulate strings.
(3) what is x'? it is never defined anywhere, we just start working with it somehow (maybe refers also to question 1)
But you do define x' as a parameter of substituteOne!
Consider the type of map:
λ> :t map
map :: (a -> b) -> [a] -> [b]
Its first argument is a function of one parameter. For your program to typecheck, the types have to line up. We can emphasize this for substituteOne by adding an optional type annotation — but have to work a bit harder (by enabling the scoped type variables extension) because substituteOne is an inner function with references to the outer scope,
substitute':: forall a. Eq a => a -> a -> [a] -> [a]
substitute' x y = map substituteOne
where
substituteOne :: a -> a
substituteOne x' | x == x' = y
| otherwise = x'
(4) map needs a function and a list, so that it works. here we have map function _. refers maybe to 2., but what would be the output of substituteOne x'?
Using unnamed arguments at the point of application as your code does with map substituteOne is known as pointfree style. In your case, there are two invisible “points” or variable names: the argument to substituteOne and the list argument to map.
You could be explicit about everything, as in
substitute'' :: Eq a => a -> a -> [a] -> [a]
substitute'' x y l = map (\x' -> if x == x' then y else x') l
but that is much more cluttered in comparison.
The values produced by substituteOne are collected in the list that results from map.
substitute has type a -> a -> [a] -> [a], which means it takes one argument and returns a function of type a -> [a] -> [a]. This is because (->) is right-associative, and the above type is equivalent to a -> (a -> [a] -> [a]).
Since function application is left-associative, a call like substitute x y is equivalent to (substitute x) y; y is the argument to the function returned by substitute x.
When one writes
substitute x y = ...
that is syntactic sugar for
substitute = \x -> \y -> ...
Further, since map substituteOne' has type [a] -> [a], that makes it a suitable value for substitute x y to return.
substitute1 takes a parameter x'. The bits between the | and = characters are guard conditions. Since this particular function has only one condition you could rewrite it like this:
substitute1 x' = if x == x' then y else x'
Because it is in the where clause substitute1 also has access to the parameters x and y of the main function.
Related
I have two functions computing the length of a list of integers
lengthFoldl :: [Int] -> Int
lengthFoldl xs = (foldl (\_ y -> y+1) 0 xs)
and
lengthFold :: [a] -> Int
lengthFold xs = foldr (\_ y -> y+1) 0 xs
they are the same except one uses foldr and one foldl.
But when trying to compute the length of any list [1 .. n] I get a wrong result (one too big) from lengthFoldl.
To complement joelfischerr's answer, I'd like to point out that a hint is given by the types of your functions.
lengthFoldl :: [Int] -> Int
lengthFold :: [a] -> Int
Why are they different? I guess you might had to change the first one to take an [Int] since with [a] it did not compile. This is however a big warning sign!
If it is indeed computing the length, why should lengthFoldl care about what is the type of the list elements? Why do we need the elements to be Ints? There is only one possible explanation for Int being needed: looking at the code
lengthFoldl xs = foldl (\_ y -> y+1) 0 xs
we can see that the only numeric variable here is y. If y is forced to be a number, and list elements are also forced to be numbers, it seems as if y is taken to be a list element!
And indeed that is the case: foldl passes to the function the accumulator first, the list element second, unlike foldr.
The general thumb rule is: when type and code do not agree, one should think carefully about which one is right. I'd say that most Haskellers would think that, in most cases, it is easier to get the type right than the code right. So, one should not just adapt the type to the code to force it to compile: a type error can instead witness a bug in the code.
Looking at the type definitions of foldl and foldr it becomes clear what the issue is.
:t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
and
:t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
One can see that the foldr takes the item of the list and the second argument into the function and foldl takes the second argument and the item of the list into the function.
Changing lengthFoldl to this solves the problem
lengthFoldl :: [Int] -> Int
lengthFoldl xs = foldl (\y _ -> y+1) 0 xs
Edit: Using foldl instead of foldl' is a bad idea: https://wiki.haskell.org/Foldr_Foldl_Foldl'
I am trying to write the map function using foldr. The problem is that when I ran this code :
> myMap f xs = foldr (\ acc x -> acc :(f x)) [] xs
I have the following problem:
No instance for (Num [a0]) arising from a use of 'it'
but when I run
myMap f xs = foldr (\x acc-> (f x):acc) [] xs
It works perfectly. Any ideas why?
the type of foldr is
foldr :: (a -> b -> b) -> b -> [a] -> b
therefore the binary operation that foldr uses to traverse and accumulate the list
has type (a -> b -> b),it first take an element of the list (type a)then the accumulator (type b) resulting in an expression of type b.
So, your first myMap function does not work becuase you are using "acc" and "x" in reverse order.
You want to apply f to x then append it to the acummulator of type b ( a list in this case)
The error you posted is not coming from your definition of myMap, it's coming from how you're using it. The type of the first myMap is ([a] -> [a]) -> [a] -> [a], which does not match the type of Prelude.map. In the second one you've swapped your variable names and also which one you're applying f to. The compiler doesn't care what you name the arguments in your lambda being passed to foldr, so foldr (\x acc -> f x : acc) is identical to foldr (\foo bar -> f foo : bar). That may be what's tripping you up here.
The second one works because (to put it simply) it's correct. In the first you're applying f to your accumulator list x (even though you have a variable named acc it's not your accumulator), so f must take a list and return a list. In the second you're applying f to each element, then prepending that to your accumulator list. If you had myMap (+1), it would have the type
myMap (+1) :: Num [a] => [a] -> [a]
Which says that you must pass it a list of values [a] where [a] implements Num, and currently there is no instance for Num [a], nor will there ever be.
TL;DR: In the first one you're applying your mapped function to your accumulator list, in the second one you're applying the mapped function to each element.
Assume
f x y z = x*y*z
Then I expect to return the application of f three times with each member of the list
foldl ($) f [1,2,3]
Something like (((f 1) 2) 3) = 1*2*3 = 6
The function f would be the accumulator and each iteration of the fold would apply one argument and return a partially applied function as the next accumulator.
Why doesn't this work? Is it because f changes type while iterating?
As an aside: is there any other way to accomplish this type of function application?
The types look like
foldl :: (a -> b -> a) -> a -> [b] -> a
($) :: (x -> y) -> x -> y
To apply foldl to ($) requires matching (technically, unifying) the type of the first argument to foldl with the type of ($). That is, solving the equation
a -> b -> a = (x -> y) -> x -> y
This leads immediately to
a = x -> y
b = x
a = y
Substituting the second and third equations into the first:
a = b -> a
The problem is that Haskell has no type that solves this equation. In particular, it is impossible to write down a solution with a finite number of symbols! It expands first to
a = b -> b -> a
then
a = b -> b -> b -> a
and on forever. So there is no way to choose types for the type variables to make them match, and GHC will complain loudly.
In general, you can't do what you're trying to do because the type system distinguishes between functions with different numbers of arguments. What you're trying to do, essentially, is convert a list of values into a list of arguments for a function, which doesn't make sense in context.
However, the instance you're pointing at is literally just foldl (*). If you're performing the same operation on all of the variables in a function, you can just use this (well, you should be using either foldl' or foldr, but you get the idea).
Hi I have a query about a simple haskell definition. I have a definition but I don't fully understand it.
The function takes in a list of functions and an item and returns a list formed by applying that function.
applyAll = \fs -> \x -> map(\n -> n x) fs
Could somebody explain what n does and why is fs outside the map function?
The spacing is misleading you. It looks like map(\n -> n x) is a function call, but the parentheses here are for grouping, not function call. map takes two arguments; the full call is map (\n -> n x) fs, where (\n -> n x) is the first argument (a lambda expression) and fs is the second.
The lambda \n -> n x is a function that takes a function as an argument and returns the result of applying that function to x. n is the argument here. The type of \n -> n x is (a -> b) -> b (where a is the type of x). If you have learned about sections yet, the lambda is equivalent to the section ($ x). If you haven't, ignore that last sentence.
The function definition:
applyAll = \fs -> \x -> map(\n -> n x) fs
is the same as:
applyAll fs x = map(\n -> n x) fs
Now you might ask, "What are those ->s doing there if they are just arguments to my function applyAll. Haskell has no concept of multi-param functions. What you see as multiple arguments to a function is just many functions chained together each with a single argument. In the case of applyAll, it's just two functions chained together:
(applyAll fs) -> x = map (\n -> n x) fs
applyAll fs is one function chained to another argument identified as x to yield a list of values returned by map.
I could try this out in ghci:
Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs
<interactive>:1:10: Not in scope: `xs'
Prelude> let xs = [1..5]
-- hah, BOOM! I told you haskell's strongly typed...
Prelude> :t applyAll xs
<interactive>:1:10:
Couldn't match expected type `t0 -> b0' with actual type `Integer'
Expected type: [t0 -> b0]
Actual type: [Integer]
In the first argument of `applyAll', namely `xs'
In the expression: applyAll xs
Prelude> let xs = [(1 +), (2 +), (3 *), (4 /)]
Prelude> :t xs
xs :: [Double -> Double]
Prelude> :t applyAll xs
applyAll xs :: Double -> [Double]
Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs 3
applyAll xs 3 :: [Double]
Prelude> applyAll xs 3
[4.0,5.0,9.0,1.3333333333333333]
What's the type of map?
map :: (a -> b) -> [a] -> [b]
This tells me that map takes a function - let's call it f and a list of values to return another list of values. The function f is one that takes a value of type a returning another of type b. So map goes on applying f to each value in the list [a] to return another list filled with values of type b.
In your applyAll, the function f is \n -> n x. This is a lambda expression(you might call it an anonymous function) taking a value identified by n and applying x to it. This goes on for every item in the input list identified by [a] in the type definition until it runs out to yield another list identified by [b] in the type definition.
Here's a simple function definition:
f x = 2*x + 1
This creates a new function f, which takes one argument. You could use it later like this:
main = print (f 3)
...which would print 7. Sometimes, it is convenient to define a function without giving it a name. The syntax for that is \{- argument -} -> {- function body -}; for example, we could do an anonymous version of f above this way:
main = print ((\x -> 2*x + 1) 3)
Now, your definition of applyAll is just doing this several times. We could explicitly name everything in where clauses if we wanted:
applyAll = outerMost where
outerMost fs = mapApply where
mapApply x = map applyToX fs where
applyToX n = n x
...though I think you'll agree that the extra verbosity doesn't make things much more clear! A more natural (but less mechanical) translation away from anonymous functions would look like this:
applyAll fs x = map applyToX fs where
applyToX n = n x
and now hopefully this can very nearly read like English: to apply all the functions fs to a single value x, we map "the function that applies a single function (which we temporarily name n) to the value x" over the list of all functions.
I am new to haskell and trying out some exercises
I dont understand whats the error generated and why it is generated
split = foldr
(\x y -> y:x)
[[]]
the error on the interpretator is as below
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `(:)', namely `y'
In the expression: y : x
In the first argument of `foldr', namely `(\ x y -> y : x)'
Failed, modules loaded: none.
anyone can help? Thanks in advance
Type of foldr is
foldr :: (a -> b -> b) -> b -> [a] -> b
so in split
split = foldr (\x y -> y:x) [[]]
y and y:x has to be of same type, which is not possible for any x and y as y:x will always be one step deeper in the list than y.
I think you wanted to do x:y?
Recall the type of foldr: (a -> b -> b) -> b -> [a] -> b. This says that foldr expects a function that combines an element of the list with a value of the final result type, producing a new value of the result type.
For the first argument, you've given foldr the function \x y -> y:x, where x will be the list elements and y the result of the next step to the right; and the result of applying this lambda should have the same type as y.
But the type of (:) is a -> [a] -> [a]--that is, it appends a single element to the head of a list. In the expression y:x, you're taking something of the "result" type and using it as an element of a list used as the result.
Because of that, GHC attempts to infer that the result type b is the same as the type [b], which is then of course the same as the type [[b]], and [[[b]]]... and so on. Thus it complains about an "infinite type".
The posts before me answer your question, but after your comment i can see that you want a function that splits your list by a predicate.
You can use groupWith::Ord b => (a -> b) -> [a] -> [[a]] from the module GHC.Exts and supply it with a function of type (a -> Bool) in your example:
groupWith even [1,2,3,4,5,6] yields [[1,3,5],[2,4,6]]
Also, something ugly but that achieves the type of "outing" you want is:
split::Eq a => (a -> Bool) -> [a] -> [[a]]
split f ls = (ls \\ rl):rl:[]
where rl = filter f ls
But this will always split the supplied list in just two lists because of the binary function you supply.