Explanation of map functions (using foldr) in Haskell? - function

I'm trying to define the map function using foldr
I have found the two following solutions, however I'm not quite sure how they are working.
map' :: (a -> b) -> [a] -> [b]
map' f = foldr ((:) . f) []
map'' :: (a -> b) -> [a] -> [b]
map'' f = foldr (\x xs -> f x : xs) []
I'm quite new to Haskell and foldr, so I'm struggling to understand what ((:) . f) in the first solution and what (\x xs -> f x : xs) in the second solution do.
I also don't get how foldr is able handle the empty list case.
It would be much appreciated if I could get a simple step by step explanation of this, in layman's terms.

Both (\x xs -> f x : xs) and (:) . f mean the same thing. They're both functions that take two arguments, apply f to the first argument, and then cons that onto the second argument.
So what does foldr do when given an empty list? It simply returns the starting value, which in these examples is [].
Here is the implementation of foldr from Hackage:
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys

Related

Replacing functions in composite function in haskell

I'm trying to become familiar with Haskell and I was wondering if the following was possible and if so, how?
Say I have a set of functions {f,g,..} for which I was to define a replacement function {f',g',..}. Now say I have a function c which uses these functions (and only these functions) inside itself e.g. c x = g (f x). Is there a way to automatically define c' x = g' (f' x) without explicitly defining it?
EDIT: By a replacement function f' I mean some function that is conceptually relates to f by is altered in some arbitrary way. For example, if f xs ys = (*) <$> xs <*> ys then f' (x:xs) (y:ys) = (x * y):(f' xs ys) etc.
Many thanks,
Ben
If, as seems to be the case with your example, f and f' have the same type etc., then you can easily pass them in as extra parameters. Like
cGen :: ([a] -> [a] -> [a]) -> (([a] -> [a]) -> b) -> [a] -> b
cGen f g x = g (f x)
...which BTW could also be written cGen = (.)...
If you want to group together specific “sets of functions”, you can do that with a “configuration type”
data CConfig a b = CConfig {
f :: [a] -> [a] -> [a]
, g :: ([a] -> [a]) -> b
}
cGen :: CConfig a b -> [a] -> b
cGen (CConfig f g) = f . g
The most concise and reliable way to do something like this would be with RecordWildCards
data Replacer ... = R {f :: ..., g :: ...}
c R{..} x = g (f x)
Your set of functions now is now pulled from the local scope from the record, rather than a global definition, and can be swapped out for a different set of functions at your discretion.
The only way to get closer to what you want would to be to use Template Haskell to parse the source and modify it. Regular Haskell code simply cannot inspect a function in any way - that would violate referential transparency.

Haskell parentheses for function application binding

I'm learning Haskell. I defined the following function (I know I don't need addToList and I can also do Point-free notation I'm just in the process of playing with language concepts):
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) map f xs
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
This produces a compile error:
with actual type `(a0 -> b0) -> [a0] -> [b0]'
Relevant bindings include
f :: a -> b (bound at PlayGround.hs:12:5)
map :: (a -> b) -> [a] -> [b] (bound at PlayGround.hs:11:1)
Probable cause: `map' is applied to too few arguments
In the second argument of `addToList', namely `map'
In the expression: addToList (f x) map f xs
If I put parantheses around map it works:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) (map f xs)
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
I understand that function application binds more tightly than operators (as discussed in Haskell - too few arguments), however, I don't understand how the compiler would parse the above differently without the parantheses.
The simple way to see that something is wrong is to note that the expression:
addToList (f x) map f xs
is applying 4 arguments to addToList whereas:
addToList (f x) (map f xs)
is applying two arguments to addToList (which is what addToList "expects").
Update
Note that even though map takes two arguments, this expression:
addToList a map c d
is parsed as:
(((addToList a) map) c) d
So here's a possible explanation of what GHC is thinking...
addToList (f x) has type [a] -> [a] - i.e. it is a function which takes a list.
map has type (c -> d) -> [c] -> [d]. It is not a list, but with additional arguments it could produce a list.
So when GHC sees addTolist (f x) map and can't type check it, it sees that if map only had a few more arguments, like this:
addToList (f x) (map ...)
at least the second argument to addToList would be a list - so perhaps that's the problem.
Parsing is a distinct step that is completed before type checking occurs. The expression
addToList (f x) map f xs
has as much meaning to the parser as s1 (s2 s3) s4 s2 s5 has to you. It doesn't know anything about what the names mean. It takes the lexical structure of the string and turns it into a parse tree like
*5
/ \
/ xs
*4
/ \
/ f
*3
/ \
/ map
*2
/ \
addToList *1
/ \
f x
Once the parse tree is complete, then each node is tagged with its type, and type checking can occur. Since function application is denoted simply by juxtaposition, the type checker knows that the left child of a node is a function, the right child is the argument, and the root is the result.
The type checker can proceed roughly as follows, doing an pre-order traversal of the tree. (I'll alter the type signatures slightly to distinguish unrelated type variables until they are unified.)
addToList :: a -> [a] -> [a], so it takes an argument of type a and returns a function of type [a] -> [a]. The value of a is not yet known.
f :: b -> c, so it takes an argument of type b and returns a value of type c. The values of b and c are not yet known.
x has type d. The value of d is not yet known.
Letting b ~ d, f can be applied to x, so *1 :: c
Letting a ~ c, addToList is applied to *1, so *2 :: [a] -> [a]
Uh oh. *2 expects an argument of type [a], but it is being applied to map :: (e -> f) -> [e] -> [f]. The type checker does not know how to unify a list type and a function type, which produces the error you see.

Inferring function type from function definition Haskell

So I was taking a test about Haskell and one question said:
let the function be
lolo g x = ys
where ys = [x] ++ filter (curry g x) ys
then determine the type of the function called lolo. The options are:
a) (a,b) -> Bool -> b -> [(a,b)]
b) (b -> b -> b) -> Bool -> [b]
c) ((b,b) -> Bool) -> b -> [b]
d) (a -> b -> Bool) -> b -> [c]
Can somebody please explain which one it is and why? I'm really confused about this one... things I do not understand are:
1) the curry function can only be applied to functions right? not datatypes that may be tuples? then you can infer that g is a function in this context? what if g and x are both functions? is it possible to use curry with nth arguments? I've only seen curry used with 1 argument.
2) the other thing I don't understand very much is the recursion in the definition of ys. so ys is defined by ys, but I don't see the base case in this scenario. Will it ever end? maybe it's the filter function that makes the recursion end.
3) also in curry g x = curry (g x) right? (this is a question about precedence in application of functions)
Thanks a lot
1) The first argument to curry has to be a function, it is what is known as a higher order function, it takes a function and returns a new one. While its type is printed out in GHCi as
curry :: ((a, b) -> c) -> a -> b -> c
It is more clearly represented (IMO) as
curry :: ((a, b) -> c) -> (a -> b -> c)
Which makes it more obvious that it takes a function and returns a new function. Technically, you could say that curry takes 3 arguments, one of type (a, b) -> c, one of type a, and one of type b. It just takes a function that normally accepts a tuple of arguments and converts it into a function that takes 2 arguments.
2) The computation for ys will never end, don't bother trying to call length on it, you'll just run the computation forever. This isn't a problem, though, you can work with infinite lists and non-terminating lists just fine (non-terminating being a list where it takes forever to compute the next element, not just one that has infinite elements). You can still use functions like take and drop on it, though.
3) Does curry g x == curry (g x)? No! When you see an expression like a b c d e, all of b, c, d, and e are arguments to a. If you instead saw a b c (d e), then e is applied to d, and that result is applied to a b c. Consider filter even [1..10], this is certainly not the same as filter (even [1..10]), since it wouldn't even compile! (even :: Integral a => a -> Bool).
When solving this sort of problem, first look at what functions are used in the expression that you already know the types of:
(++) :: [a] -> [a] -> [a]
filter :: (b -> Bool) -> [b] -> [b]
curry :: ((c, d) -> e) -> c -> d -> e
I've used different type variables in each so that there will be less confusion when trying to line up the types. You can get these types by loading up GHCi, then typing
> :type (++)
(++) :: [a] -> [a] -> [a]
> -- Or just use :t
> :t filter
filter :: (a -> Bool) -> [a] -> [a]
> :t curry
curry :: ((a, b) -> c) -> a -> b -> c
As you can see, I've changed filter to use b instead of a, and curry to use c, d, and e. This doesn't change the meaning any more than f x = x + 1 versus f y = y + 1, it'll just make it easier to talk about.
Now that we've broken down our function into its subcomponents, we can work from the "top" down. By top, I mean the last function that gets called, namely (++). You can picture this function by a tree like
(++)
/ \
[x] filter
/ \
curry ys
/ \
g x
So we can clearly see that (++) is at the top. Using that, we can infer that [x] has the type [a], which means that x ~ a (the tilde is the type equality symbol) and consequently ys ~ [a], since ys = [x] ++ something. Now that we know the type of x, we can start filling out the rest of the expression. Next, we work down to filter (curry g x) ys. Since it is the second argument to (++), we can infer that this subexpression also has the type [a]. If we look at the type of filter:
filter :: (b -> Bool) -> [b] -> [b]
The final result is a list of type [b]. Since it's being applied to [x] ++, we can infer that filter (curry g x) ys :: [a]. This means that [b] ~ [a] => b ~ a. For reference, this makes filter's type
filter :: (a -> Bool) -> [a] -> [a]
This now places a constraint on curry g x, it must fit into filter's first argument which has the type a -> Bool. Looking at curry's type again:
curry :: ((c, d) -> e) -> c -> d -> e
This means that e ~ Bool, and d ~ a. If we plug those back in
curry :: ((c, a) -> Bool) -> c -> a -> Bool
Ignoring g for now, we look at the type of x, which we figured out is a. Since x is the second argument to curry, that means that x matches with the argument of type c, implying that c ~ a. Substituting this into what we just computed we get
curry :: ((a, a) -> Bool) -> a -> a -> Bool
With
curry g x :: a -> Bool
filter (curry g x) :: [a] -> [a]
filter (curry g x) ys :: [a]
[x] ++ filter (curry g x) ys :: [a]
From this we can directly infer that lolo's type signature ends with [a], so
lolo :: ??? -> [a]
I'll leave you to do the remaining few steps to figure out what ??? is.

iterate function in haskell

How can be iterate function modified that the result will be
f x, (f^2)x, (f^4)x, (f^8)x, ...
I'd be very happy if anybody could provide me with any suggestion.
Given, that f^x means f x-times applied to x I would say
iterate :: (a -> a) -> a -> [a]
iterate f x = f x : iterate (f . f) x
would suffice.
Alternative:
Prelude> map snd $ iterate (\(f,x) -> (f.f, f x)) ((+1),1)
[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,...

Function application: Why is $ used here?

A while ago, I asked a question about $, and got useful answers -- in fact, I thought I understood how to use it.
It seems I was wrong :(
This example shows up in a tutorial:
instance Monad [] where
xs >>= f = concat . map f $ xs
I can't for the life of me see why $ was used there; ghci isn't helping me either, as even tests I do there seem to show equivalence with the version that would simply omit the $. Can someone clarify this for me?
The $ is used here because it has lower precedence than normal function application.
Another way to write this code is like so:
instance Monad [] where
xs >>= f = (concat . map f) xs
The idea here is to first construct a function (concat . map f) and then apply it to its argument (xs). As shown, this can also be done by simply putting parenthesis around the first part.
Note that omitting the $ in the original definition is not possible, it will result in a type error. This is because the function composition operator (the .) has a lower precedence than normal function application effectively turning the expression into:
instance Monad [] where
xs >>= f = concat . (map f xs)
Which doesn't make sense, because the second argument to the function composition operator isn't a function at all. Although the following definition does make sense:
instance Monad [] where
xs >>= f = concat (map f xs)
Incidentally, this is also the definition I would prefer, because it seems to me to be a lot clearer.
I'd like to explain why IMHO this is not the used style there:
instance Monad [] where
xs >>= f = concat (map f xs)
concat . map f is an example of so-called pointfree-style writing; where pointfree means "without the point of application". Remember that in maths, in the expression y=f(x), we say that f is applied on the point x. In most cases, you can actually do a final step, replacing:
f x = something $ x
with
f = something
like f = concat . map f, and this is actually pointfree style.
Which is clearer is arguable, but the pointfree style gives a different point of view which is also useful, so sometimes is used even when not exactly needed.
EDIT: I have replaced pointless with pointfree and fixed some examples, after the comment by Alasdair, whom I should thank.
The reason $ is used here is doe to the type signature of (.):
(.) :: (b -> c) -> (a -> c) -> a -> c
Here we have
map f :: [a] -> [[b]]
and
concat :: [[b]] -> [b]
So we end up with
concat . map f :: [a] -> [b]
and the type of (.) could be written as
(.) :: ([[b]] -> [b]) -> ([a] -> [[b]]) -> [a] -> [b]
If we were to use concat . map f xs, we'd see that
map f xs :: [[b]]
And so cannot be used with (.). (the type would have to be (.) :: (a -> b) -> a -> b