I'm writing a prefix function that will take a binary function and a list of numbers as parameters, and returns a list formed by computing the successive function and accumulating as you go.
To make things simple, Here's an example:
prefix (+) [2, 4, 1, 1]
returns [2, 6, 7, 8]
prefix (+) [0, 2, -3, 4, -5]
returns [0, 2, -1, 3, -2]
prefix max [2, 3, 1, 1]
returns [2, 3, 3, 3]
Here's my code so far however I get an error when i try to load the file because 'list is not in range'. How can i rewrite it so it makes sense to the compiler? Any help will be appreciated.
prefix' :: (a -> b) -> [a] ->[b]
prefix' _ [] = []
prefix' f (x:xs)
| ((list !! x) == 0) = f (list !! 0) (list !! 0)
| otherwise = prefix' f xs
Try this
prefix::(a -> a -> a) -> [a] -> [a]
prefix f lst| null lst = []
| null (tail lst) = lst
| otherwise = h : prefix' f (f h) (tail lst) where
h = head lst
prefix' fn fc (x:xs) | null xs = [acc]
| otherwise = acc : prefix' fn (fn acc) xs where
acc = fc x
I will try to explain the above code as much as possible. The type signature of the function is one that takes a function (a->a->a) and a list [a] as parameter and returns another list with that function applied to each adjacent pair of the list. The a in the parameter list simply implies any type (which can be anything). If we had specified a specific type (i.e. in Title case), the function will only work with that specific type
The function works by first checking if the list it recieved is empty (null lst), if so we simply return an empty list
The next thing it checks for is if the list only contains one item in it (null (tail lst)), in that case, we simply return the list
The third case is when we actually do something, and the first thing we do is to append the first element in the list to head of our new list (head lst) and call another function which we have defined on the fly to do compute the rest of the list (: prefix' f (f (head lst)) (tail lst)). Note the : separates the head from the rest of the list
The prefix' function has a type signature of (a -> a -> a) -> (a -> a) -> [a] -> [a] so as you can see the only thing different about it is that it takes one extra parameter which is a function (fc) that takes an element of type a and returns an element of type a. To create this function, we have simply passed one parameter to the initial function recieved as argument which creates this new function. This will be useful in computing the rest of the list
The base case for this new function is that if the list only contains one element, it applies the new parameter function fc to that element in the list and returns a list containing the return value of the function
Otherwise it will apply fc to the first element of the list and we generate fc again by applying fn to the return value of fc x.
If you are interested in learning how all these work, this is the website I've been using and my knowledge of haskell has improved greatly due to this website, so highly recommended
Isn't what you want to implement the scanl1 function? I'm a beginner too, but from what I understood, it goes like this:
scanl1 :: (a -> a -> a) -> [a] -> [a]
scanl1 f (x:xs) = scanl f x xs
scanl1 _ [] = []
The scanl function. which scanl1 uses, goes like this:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl = scanlGo
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo f q ls = q : (case ls of
[] -> []
x:xs -> scanlGo f (f q x) xs)
Here's what hackage has to say about scanl:
scanl :: (b -> a -> b) -> b -> [a] -> [b] Source
scanl is similar to foldl, but returns a list of successive reduced values from the left:
scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
Note that
last (scanl f z xs) == foldl f z xs.
So, I guess the flow of execution goes like this:
scanl1 (+) [2, 4, 1, 1]
scanl (+) 2 [4, 1, 1]
scanlGo (+) 2 [4, 1, 1]
2 : scanlGo (+) (+ 2 4) [1, 1]
2 : 6 : scanlGo (+) (+ 6 1] [1]
2 : 6 : 7 : scanlGo (+) (+ 7 1) []
2 : 6 : 7 : 8 : scanlGo []
2 : 6 : 7 : 8 : []
[2, 6, 7, 8]
The same thing happens with the (*) and the max functions that you mentioned. Hope this helps.
Related
First I would like to apologize if I am not asking the correct question. I realize that there are some fundamental concepts that I don't quite understand about Monads and the bind operator which is making it difficult to formulate my question. I am having a hard time wrapping my head around how the following code is creating a list of tuples.
ordPairs :: Ord a => [a] -> [(a, a)]
ordPairs xs =
xs >>= \x1 ->
xs >>= \x2 ->
if x1 < x2 then [(x1, x2)] else []
main = print $ ordPairs [1, 2, 4, 6, 7, 8, 3, 4, 5, 6, 2, 9, 7, 8, 45, 4]
I understand the type declaration states that it returns a list of tuples [(a, a)]. What I can't figure out is how is this code "looping" through each item in the list? Looking at this as a beginner it looks as if it only passes the first and second item forward x1 and x2 and then ends with the if then else expression. Is this code being desugared into multiple iterations and building the list under the hood? I guess what I am asking is how is this code iterating through each item in the list and building a list of tuples at the end?
It might help to understand "where the parentheses are". The right-hand side of the ordPairs definitions is parsed like this:
xs >>= (\x1 -> xs >>= (\x2 -> if x1 < x2 then [(x1, x2)] else []))
As you can see here, the if-then-else expression does not stand alone, it's actually the body of an anonymous function:
\x2 -> if x1 < x2 then [(x1, x2)] else []
which can, obviously, be invoked multiple times for different values of x2. What invokes it? Well, the second >>= operator, of course. The "outer" loop works similarly, with the first >>= operator invoking another anonymous function multiple times:
\x1 -> xs >>= (\x2 -> ...)
For this example, you could replace the >>= operator with your own custom bind function. Note that it's just a plain function. There's no special desugaring or secret iterating going on. The function itself does the iterating using recursion:
bind :: [a] -> (a -> [b]) -> [b]
bind (x:xs) f = f x ++ bind xs f
bind [] _ = []
You could also write bind like this, if you prefer:
bind xs f = concatMap f xs
-- or even `bind = flip concatMap`, as per #WillemVanOnsem's comment
Or as a list comprehension.
bind xs f = [y | x <- xs, y <- f x]
This last one is the actual definition of the >>= operator for the list monad. See GHC/Base.hs.
With any of these definitions, the following will work just like your original:
bind :: [a] -> (a -> [b]) -> [b]
bind (x:xs) f = f x ++ bind xs f
bind [] _ = []
ordPairs :: Ord a => [a] -> [(a, a)]
ordPairs xs =
xs `bind` \x1 ->
xs `bind` \x2 ->
if x1 < x2 then [(x1, x2)] else []
main = print $ ordPairs [1,2,4,6,7,8,4,5,6,2,9,7,8,45,4]
I have hard time understanding how these bits of code work.
"Map" function must apply the function to all elements in given list, and generate list consist of results of applying. So we are giving our function f and some list, then in lambda expression our list transforms into head "x" and tail "xs", we applying function "f" to x and append it to "xs". But what happens next? How and what exactly foldr takes for its second argument (which must be some starting value usually). And for what purpose empty list?
And function "rangeTo" : we are creating lambda expression, where we are checking that we are over the end of range, end if we are than we are giving Nothing, or if we are not at end, we are giving pair where first number append to resulting list, and second number used as next value for "from". Is it all what happens in this function, or I'm missing something?
--custom map function through foldr
map :: (a -> b) -> [a] -> [b]
map f = foldr (\x xs -> f x : xs) []
--function to create list with numbers from first argument till second and step "step"
rangeTo :: Integer -> Integer -> Integer -> [Integer]
rangeTo from to step = unfoldr (\from -> if from >= to then Nothing else Just (from, from+step)) from
To understand How foldr operates on a list. It is better to write down the definition of foldr as
foldr step z xs
= x1 `step` foldr step z xs1 -- where xs = x:xs1
= x1 `step` (x2 `step` foldr step z xs2) -- where xs = x1:x2:xs2
= x1 `step` (x2 `step` ... (xn `step` foldr step z [])...) -- where xs = x1:x2...xn:[]
and
foldr step z [] = z
For your case:
foldr (\x xs -> f x : xs) []
where
step = (\x xs -> f x : xs)
z = []
From the definition of foldr, the innermost expression
(xn `step` foldr step z [])
is evaluated first, that is
xn `step` foldr step z []
= step xn (foldr step z [])
= step xn z
= step xn [] -- z = []
= f xn : [] -- step = (\x xs -> f x : xs)
= [f xn]
what happens next? The evaluation going on as
x(n-1) `step` (xn `step` foldr step z [])
= step x(n-1) [f xn]
= f x(n-1) : [f xn]
= [f x(n-1), f xn]
untill:
x1 `step` (x2 ...
= step x1 [f x2, ..., f xn]
= [f x1, f x2, ... f xn]
So we are giving our function f and some list, then in lambda expression our list transforms into head "x" and tail "xs", we applying function "f" to x and append it to "xs".
This is not the case. Look closely at the implementation:
map :: (a -> b) -> [a] -> [b]
map f = foldr (\x xs -> f x : xs) []
There is an implied variable here, we can add it back in:
map :: (a -> b) -> [a] -> [b]
map f ls = foldr (\x xs -> f x : xs) [] ls
map takes two arguments, a function f and a list ls. It passes ls to foldr as the list to fold over, and it passes [] as the starting accumulator value. The lambda takes a list element x and an accumulator xs (initially []), and returns a new accumulator f x : xs. It does not perform a head or tail anywhere; x and xs were never part of the same list.
Let's step through the evaluation to see how this function works:
map (1+) [2, 4, 8]
foldr (\x xs -> (1+) x : xs) [] [2, 4, 8] -- x = 8, xs = []
foldr (\x xs -> (1+) x : xs) [9] [2, 4] -- x = 4, xs = [9]
foldr (\x xs -> (1+) x : xs) [5, 9] [2] -- x = 2, xs = [5, 9]
foldr (\x xs -> (1+) x : xs) [3, 5, 9] [] -- xs = [3, 5, 9]
map (1+) [2, 4, 8] == [3, 5, 9]
The empty list accumulates values passed through f, starting from the right end of the input list.
And function "rangeTo" : we are creating lambda expression, where we are checking that we are over the end of range, end if we are than we are giving Nothing, or if we are not at end, we are giving pair where first number append to resulting list, and second number used as next value for "from". Is it all what happens in this function, or I'm missing something?
Yes, that's exactly what's going on. The lambda takes an accumulator, and returns the next value to put in the list and a new accumulator, or Nothing if the list should end. The accumulator in this case is the current value in the list. The list should end if that value is past the end of the range. Otherwise it calculates the next accumulator by adding the step.
Again, we can step through the evaluation:
rangeTo 3 11 2 -- from = 3, to = 11, step = 2
Just (3, 5) -- from = 3
Just (5, 7) -- from = 3 + step = 5
Just (7, 9) -- from = 5 + step = 7
Just (9, 11) -- from = 7 + step = 9
Nothing -- from = 9 + step = 11, 11 >= to
rangeTo 3 11 2 == [3, 5, 7, 9]
I have been struggling with following problem for sometime. I spent many hours on the internet to find a viable algorithm in Haskell using recursive functions only but no success.
Define a recursive function funkyMap :: (a -> b) -> (a -> b) -> [a] -> [b] that takes as arguments two functions f and g and a list xs, and applies f to all elements at even positions ([0, 2..]) in xs and g to all elements at odd positions ([1, 3..]) in xs.
Example: funkyMap (+10) (+100) [1, 2, 3, 4, 5] = [(+10) 1, (+100) 2, (+10) 3, (+100) 4, (+10) 5].
To above problem, I attempted following solution, but HUGS give me compilation error "unification would give infinite type".
mapEven :: (a->a) -> [a] -> [a]
mapEven f [] = []
mapEven f (x:xs) = f x : mapOdd f xs
mapOdd :: (a->a) -> [a] -> [a]
mapOdd g [] = []
mapOdd g (x:xs) = x : mapEven g xs
funkyMap :: (a -> b) -> (a -> b) -> [a] -> [b]
funkyMap f g [] = []
funkyMap f g (x:xs) = (mapEven f x) ++ (mapOdd g xs)
Please suggest an alternate working solution.
Thanks
This line has a problem:
funkyMap f g (x:xs) = (mapEven f x) ++ (mapOdd g xs)
x is an element of the list (ie type a), while xs is another list (type [a]). But you are treating them the same. The error you are getting is because the only way to make sense of a list and an element being the same type is if it's a list of lists of lists of lists of lists...
By God's mercy, I got some inspiration and I seemed to have cracked this problem.
Please review the following solution:
h1 p q [] = []
h1 p q ((cnt, val) : xs) = (if odd cnt then (q val) else (p val) ) : h1 p q xs
funkyMap f g xs = h1 f g ( zip [0..] xs)
If I try funkyMap (+10) (+100) [1, 2, 3, 4, 5] I get [11,102,13,104,15] which is expected.
Also funkyMap (+100) (+2) [1] gives
[101]
and funkyMap (+100) (+2) [] gives
[]
Please review this solution and let me know your feedback.
Thanks
I've been trying to wrap my head around foldr and foldl for quite some time, and I've decided the following question should settle it for me. Suppose you pass the following list [1,2,3] into the following four functions:
a = foldl (\xs y -> 10*xs -y) 0
b = foldl (\xs y -> y - 10 * xs) 0
c = foldr (\y xs -> y - 10 * xs) 0
d = foldr (\y xs -> 10 * xs -y) 0
The results will be -123, 83, 281, and -321 respectively.
Why is this the case? I know that when you pass [1,2,3,4] into a function defined as
f = foldl (xs x -> xs ++ [f x]) []
it gets expanded to ((([] ++ [1]) ++ [2]) ++ [3]) ++ [4]
In the same vein, What do the above functions a, b, c, and d get expanded to?
I think the two images on Haskell Wiki's fold page explain it quite nicely.
Since your operations are not commutative, the results of foldr and foldl will not be the same, whereas in a commutative operation they would:
Prelude> foldl1 (*) [1..3]
6
Prelude> foldr1 (*) [1..3]
6
Using scanl and scanr to get a list including the intermediate results is a good way to see what happens:
Prelude> scanl1 (*) [1..3]
[1,2,6]
Prelude> scanr1 (*) [1..3]
[6,6,3]
So in the first case we have (((1 * 1) * 2) * 3), whereas in the second case it's (1 * (2 * (1 * 3))).
foldr is a really simple function idea: get a function which combines two arguments, get a starting point, a list, and compute the result of calling the function on the list in that way.
Here's a nice little hint about how to imagine what happens during a foldr call:
foldr (+) 0 [1,2,3,4,5]
=> 1 + (2 + (3 + (4 + (5 + 0))))
We all know that [1,2,3,4,5] = 1:2:3:4:5:[]. All you need to do is replace [] with the starting point and : with whatever function we use. Of course, we can also reconstruct a list in the same way:
foldr (:) [] [1,2,3]
=> 1 : (2 : (3 : []))
We can get more of an understanding of what happens within the function if we look at the signature:
foldr :: (a -> b -> b) -> b -> [a] -> b
We see that the function first gets an element from the list, then the accumulator, and returns what the next accumulator will be. With this, we can write our own foldr function:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f a [] = a
foldr f a (x:xs) = f x (foldr f a xs)
And there you are; you should have a better idea as to how foldr works, so you can apply that to your problems above.
The fold* functions can be seen as looping over the list passed to it, starting from either the end of the list (foldr), or the start of the list (foldl). For each of the elements it finds, it passes this element and the current value of the accumulator to what you have written as a lambda function. Whatever this function returns is used as the value of the accumulator in the next iteration.
Slightly changing your notation (acc instead of xs) to show a clearer meaning, for the first left fold
a = foldl (\acc y -> 10*acc - y) 0 [1, 2, 3]
= foldl (\acc y -> 10*acc - y) (0*1 - 1) [2, 3]
= foldl (\acc y -> 10*acc - y) -1 [2, 3]
= foldl (\acc y -> 10*acc - y) (10*(-1) - 2) [3]
= foldl (\acc y -> 10*acc - y) (-12) [3]
= foldl (\acc y -> 10*acc - y) (10*(-12) - 3) []
= foldl (\acc y -> 10*acc - y) (-123) []
= (-123)
And for your first right fold (note the accumulator takes a different position in the arguments to the lambda function)
c = foldr (\y acc -> y - 10*acc) 0 [1, 2, 3]
= foldr (\y acc -> y - 10*acc) (3 - 10*0) [1, 2]
= foldr (\y acc -> y - 10*acc) 3 [1, 2]
= foldr (\y acc -> y - 10*acc) (2 - 10*3) [1]
= foldr (\y acc -> y - 10*acc) (-28) [1]
= foldr (\y acc -> y - 10*acc) (1 - 10*(-28)) []
= foldr (\y acc -> y - 10*acc) 281 []
= 281
I want to do a list of concatenations in Haskell.
I have [1,2,3] and [4,5,6]
and i want to produce [14,15,16,24,25,26,34,35,36].
I know I can use zipWith or sth, but how to do equivalent of:
foreach in first_array
foreach in second_array
I guess I have to use map and half curried functions, but can't really make it alone :S
You could use list comprehension to do it:
[x * 10 + y | x <- [1..3], y <- [4..6]]
In fact this is a direct translation of a nested loop, since the first one is the outer / slower index, and the second one is the faster / inner index.
You can exploit the fact that lists are monads and use the do notation:
do
a <- [1, 2, 3]
b <- [4, 5, 6]
return $ a * 10 + b
You can also exploit the fact that lists are applicative functors (assuming you have Control.Applicative imported):
(+) <$> (*10) <$> [1,2,3] <*> [4,5,6]
Both result in the following:
[14,15,16,24,25,26,34,35,36]
If you really like seeing for in your code you can also do something like this:
for :: [a] -> (a -> b) -> [b]
for = flip map
nested :: [Integer]
nested = concat nested_list
where nested_list =
for [1, 2, 3] (\i ->
for [4, 5, 6] (\j ->
i * 10 + j
)
)
You could also look into for and Identity for a more idiomatic approach.
Nested loops correspond to nested uses of map or similar functions. First approximation:
notThereYet :: [[Integer]]
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
That gives you nested lists, which you can eliminate in two ways. One is to use the concat :: [[a]] -> [a] function:
solution1 :: [Integer]
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3])
Another is to use this built-in function:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)
Using that:
solution2 :: [Integer]
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
Other people have mentioned list comprehensions and the list monad, but those really bottom down to nested uses of concatMap.
Because do notation and the list comprehension have been said already. The only other option I know is via the liftM2 combinator from Control.Monad. Which is the exact same thing as the previous two.
liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
The general solution of the concatenation of two lists of integers is this:
concatInt [] xs = xs
concatInt xs [] = xs
concatInt xs ys = [join x y | x <- xs , y <- ys ]
where
join x y = firstPart + secondPart
where
firstPart = x * 10 ^ lengthSecondPart
lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y))
secondPart = y
Example: concatInt [1,2,3] [4,5,6] == [14,15,16,24,25,26,34,35,36]
More complex example:
concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44,3,224,22,2999,244,23,1024,102,10999,1044,103,124,12,1999,144,13,10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]