Haskell - Invoke function from a pair [duplicate] - haskell

This question already has answers here:
Haskell: Double every 2nd element in list
(6 answers)
Closed 4 years ago.
If f1 and f2 are two functions, I want to be able to invoke f1 and f2 alternatively on a list. I came up with following:
[ ((snd p) (fst p)) | p <- zip [1,2,3,4] (repeat [f1, f2])]
The above does not work:
Couldn't match expected type ‘Integer -> t’
with actual type ‘[Integer -> Integer]’
• The function ‘snd’ is applied to two arguments,
How do I apply function which is evaluated as second of the pair?
Update:
Applying the function was right, as pointed out in the answers and comments. The problem was with: zip [1,2,3,4] (repeat [f1, f2])

You want to use cycle and zipWith:
zipWith id (cycle [f1, f2]) [1..4]
cycle makes a finite list infinite by, well, cycleing it:
cycle [f1, f2] = [f1, f2, f1, f2, f1, f2, f1, f2, ...]
-- it is equivalent to (but is not implemented by)
cycle = concat . repeat
-- repeat :: a -> [a]; repeats a single element forever
-- concat :: [[a]] -> [a]; concatenates all the lists together
-- concat . repeat :: [a] -> [a]; concatenates infinitely many copies of the input
-- this forms a (inefficient) cycle
zipWith id takes a list of functions and a list of arguments and applies them pairwise:
zipWith id [f1, f2, f1, f2, ...]
[1 , 2 , 3 , 4 ]
= [id f1 1, id f2 2, id f1 3, id f2 4]
= [f1 1, f2 2, f1 3, f2 4]
Note that ($) = id (just a more restricted type), so you can also write zipWith ($).

Related

Haskell Functions (map,foldr, foldl)

I am struggling to think of a way to utilize these functions for this beginner level coding class that I am taking to learn functional programming in Haskell. The functions I have to write are shown below, asum is supposed to turn a list of integers [a1,a2,..,an] into the alternating sum a1-a2+a3-a4+.… and I am not sure how to approach it with these functions. The xor function is supposed to that computes the XOR of a list of Booleans. I need some help to understand how to use these functions and it would greatly appreciated. I am also new to Haskell so any explanations would help. Thanks I have to use map foldr foldl.
asum :: (Num a) => [a] -> a
xor :: [Bool] -> Bool
I would say start by running the following, one by one, in GHCi:
:t foldr
:info foldr
:doc foldr
:t foldl
:info foldl
:doc foldl
:t map
:info map
:doc map
Or better, open hoogle.haskell.org and search each of the above mentioned functions and click on the first link.
But I agree that Haskell documentation are difficult to read, especially for beginners. I'm a beginner and I have a lot of difficulty reading and understanding them.
Here's a function that uses map and foldr to show how foldr works:
printFoldr xs = foldr (\x acc -> "(" ++ x ++ " + " ++ acc ++ " )") "0" $ map show xs
Now running watch this:
printFoldr [1..5]
-- outputs the following:
"(1 + (2 + (3 + (4 + (5 + 0 ) ) ) ) )"
This shows us how foldr is evaluated. Before going into how foldr is evaluated, let's look briefly at map.
map show [1..5]
-- outputs the following:
["1","2","3","4","5"]
This means that map takes 2 arguments. A list and a function that is applied to each element of the list. The result is a new list with the function applied to each element. Thus, applying show to each number outputs their string representation.
Back to foldr. foldr takes 3 arguments:
a function of type a -> b -> b
an initial value of type b
a list of type [a]
foldr takes each and every value of the provided list and applies this function to it. What is special is that map retains the output of the function over each iteration and passes it to the function as its second argument on the next run. Therefore it is convenient to write the function that is passed foldr as follows: (\el acc -> do something). Now on the next iteration of foldr, acc will hold the value of the previous run and el will be the current element from the list. BTW, acc stands for accumulator and el for element. This enables us to reduce elements of the provided list to something completely new.
As you can see in printFoldr, the initial value is just an empty string but it gradually adds the lists elements to it showing how it would have reduced the elements of the list to their sum.
Here's an idea:
a1-a2+a3-a4+...
=
a1-(a2-(a3-(a4-(...(an-0)...))))
This fits pretty well to the foldr pattern of recursion,
foldr f z [a1,a2,a3,a4,...,an]
=
a1`f`(a2`f`(a3`f`(a4`f`(...(an`f`z)...))))
So it can be coded by setting f = ... and z = ... and calling
asum :: (Num a) => [a] -> a
asum xs = foldr f z xs
where
f = (...)
z = (...)
You will need to complete this definition.
For the XOR of a list of Booleans, assuming it is to be True if one and only one of them is True, and False otherwise, we can imagine this sequence of transformations:
[ True, False, False, True, True, False, ...]
==>
[ t, f, f, t, t, f, ...]
where t and f are some specially chosen numbers. And then we can find the sum of this second list (not alternating sum, just a sum of a list of numbers) and check whether it is equal to ... some (other?) special number, let's call it n1:
xor :: [Bool] -> Bool
xor bools = (aNumber ... n1)
where
list1 = bools
list2 = fun1 transform list1
transform False = f
transform True = t
f = ...
t = ...
aNumber = sum list2
n1 = ...
fun1 = ...
sum listOfNums = ...
fun1 is the function which transforms each element of its argument list according to the given function, called transform above. It is one of the two functions left from the three you were given, considering we've already been using foldr.
sum is to be implemented by using the last function that's left.
FYI,
map foo [a1,a2,a3,...,an]
=
[foo a1, foo a2, foo a3, ..., foo an]
and
foldl f z [a1,a2,a3,...,an]
=
((((z`f`a1)`f`a2)`f`a3)...)`f`an

How to map a function taking two parameters (instead of one)?

I have a Haskell problem and I came up with a solution but I just can't put pen to paper.
Basically I have a function calc that takes in an Int and returns a Float.
calc :: Int -> Int -> Float
In my function g I want to apply this function on an array
g :: [Int] -> [Float]
Since calc takes two Int parameters I want to consume two Ints (
x being the first index of the array and x+1 being second index). This will keep repeating the function on (index of array) [1][2], [2][3], [3][4] etc.
g :: [Int] -> [Float]
g [] = ""
g (x:xs) = map calc x x+1
calc :: Int -> Int -> Float
calc current last = (current - last / last) * 100
I've tried to research online on how to use map and it basically said like this? Any idea why the code doesn't want to compile and if x+1 is even a viable?
Unary map is map but binary map is zipWith. So what's to zip together? The two copies of the same list, shifted by one position one against the other:
calc :: Int -> Int -> Float
g :: [Int] -> [Float]
g xs = zipWith calc xs (drop 1 xs)
This is all. The zipping automatically stops when the shorter sequence runs out.
zipWith foo applies foo to each pair of arguments, each argument coming from the corresponding list, one element after the other. It could be implemented using zip as
zipWith foo xs ys = map (\ (x,y) -> foo x y) $ zip xs ys
= [ foo x y | (x,y) <- zip xs ys ]
but it already does this by itself.
As an illustration, drop 1 [1,2,3] == [2,3] and this means that
zipWith calc [1, 2, 3] (drop 1 [1, 2, 3]) ==
zipWith calc [1, 2, 3]
[2, 3 ] ==
[calc 1
2,
calc 2
3]
You wanted to use indices. Indices are practically never used in Haskell with lists. We instead achieve the same effect by structural jiggling, and then when we advance along the two lists one element at a time, each operation is O(1) because the next element is already at the top of the advanced list. Whereas with the indices we'd have to traverse the same list from the top anew each time, leading to O(k) time per each one (kth) element, i.e. quadratic behavior overall.
update: taking the zipping approach leads to a possibility of code fusion,
g2 xs = zipWith calc xs (drop 1 xs)
= [calc x y | (x,y) <- zip xs (drop 1 xs)]
= [calc x y | (x:y:_) <- tails xs] -- tails ~= iterate (drop 1)
because why build a new structure to house the two consecutive elements when they already appear in a structure ... the original list structure.
Interestingly, Common Lisp has this special kind of map, a map on tails, as part of the language. While the regular map is known there as mapcar, the map on tails is known there as maplist (it's a map on non-empty tails, to be precise).
I think the best a solution is
-- Returns the empty list on empty list due to laziness of zip
g xs = uncurry calc `map` zip xs (tail xs)
-- | |- this is the list of pairs with indeces: [(1,2), (2,3), (3,4) ...]
-- |- this converts a two arguments functions on a function with single 2-tuple argument
EDIT: #Will Ness solution is actually better.

Haskell: Purpose of the flip function?

I am a bit surprised that this was not asked before. Maybe it is a stupid question.
I know that flip is changing the order of two arguments.
Example:
(-) 5 3
= 5 - 3
= 2
flip (-) 5 3
= 3 - 5
= -2
But why would I need such a function? Why not just change the inputs manually?
Why not just write:
(-) 3 5
= 3 - 5
= -2
One is unlikely to ever use the flip function on a function that is immediately applied to two or more arguments, but flip can be useful in two situations:
If the function is passed higher-order to a different function, one cannot simply reverse the arguments at the call site, since the call site is in another function! For example, these two expressions produce very different results:
ghci> foldl (-) 0 [1, 2, 3, 4]
-10
ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
2
In this case, we cannot swap the arguments of (-) because we do not apply (-) directly; foldl applies it for us. So we can use flip (-) instead of writing out the whole lambda \x y -> y - x.
Additionally, it can be useful to use flip to partially apply a function to its second argument. For example, we could use flip to write a function that builds an infinite list using a builder function that is provided the element’s index in the list:
buildList :: (Integer -> a) -> [a]
buildList = flip map [0..]
ghci> take 10 (buildList (\x -> x * x))
[0,1,4,9,16,25,36,49,64,81]
Perhaps more frequently, this is used when we want to partially apply the second argument of a function that will be used higher-order, like in the first example:
ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
[[2,3,4],[2,4,6]]
Sometimes, instead of using flip in a case like this, people will use infix syntax instead, since operator sections have the unique property that they can supply the first or second argument to a function. Therefore, writing (`f` x) is equivalent to writing flip f x. Personally, I think writing flip directly is usually easier to read, but that’s a matter of taste.
One very useful example of flip usage is sorting in descending order. You can see how it works in ghci:
ghci> import Data.List
ghci> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
ghci> :t compare
compare :: Ord a => a -> a -> Ordering
ghci> sortBy compare [2,1,3]
[1,2,3]
ghci> sortBy (flip compare) [2,1,3]
[3,2,1]
Sometimes you'll want to use a function by supplying the second parameter but take it's first parameter from somewhere else. For example:
map (flip (-) 5) [1..5]
Though this can also be written as:
map (\x -> x - 5) [1..5]
Another use case is when the second argument is long:
flip (-) 5 $
if odd x
then x + 1
else x
But you can always use a let expression to name the first parameter computation and then not use flip.

Applying tuple of functions to a tuple

I'm trying to apply a tuple of functions to a tuple of values
λ> let foo = ((+1), (*3), ((:)5)) #Each function has type: a -> a
λ> let bar = (1, 5, [0]) #Each value of the corresponding tuple has type a
How do I implement:
toImplement foo bar = ?
such that:
λ> toImplement foo bar
-> (2, 15, [0,5]) # using foo and bar above
How can you implement this in general for any valid foo and bar (of the same length)?
[I looked at this problem, but it is implemented for a fixed type. I require a general implementation]
Motivation:
I'm trying to write folds efficiently.
let acc1 = \x acc -> x*x:acc
let acc2 = (+)
foldr (\x acc -> (acc1 x (fst acc), acc2 x ( snd acc))) ([],0) [1..10]
> ([1,4,9,16,25,36,49,64,81,100],55)
I have 2 different accumulators acc1 & acc2 that loop over the list exactly once. I'd like to do this for arbitrary number of accumulators all of whom have type a -> b [where a is the type of the elements in the list and b is of the type of the output of the accumulator]
It looks clumsy, having to access the tuples using fst and snd :/
As mentioned in the comments, haskell does not allow one to implement generic functions for tuples of arbitrary size. Hence you need to implement a particular function for every size separately.
Eg:
toImplement3 :: (b0 -> c0, b1 -> c1, b2 -> c2) -> (b0, b1, b2) -> (c0, c1, c2)
toImplement3 (f1, f2, f3) (a1, a2, a3) = (f1 a1, f2 a2, f3 a3)

Haskell mapping function to list

I am new to Haskell and I have the following problem. I have to create a list of numbers [f1, f2, f3...] where fi x = x ^ i. Then I have to create a function that applies the fi to a list of numbers. For example if I have a list lis = [4,5,6,7..] the output would be [4^1, 5^2,6^3, 7^4...]. This is what I have written so far :
powers x= [x^y |y<-[1,2,3,4]]
list = [1,2,3,4]
match :: (x -> xs) -> [x] -> [xs]
match f [] = []
match f (x:xs) = (f x) : ( match f xs )
So if I put the list = [1,2,3] the output is [1,1,1,1][2,4,8,16],[3,9,27,81] instead of [1,4,27]
Can you please tell me what is wrong and point me to the right direction?
The first issue is that powers is of type Int -> [Int]. What you really want, I think, is something of type [Int -> Int] -- a list of Int -> Int functions instead of a function that takes an Int and returns a list of Int. If you define powers like so:
powers = [(^y) | y <- [1..4]]
you can use zipWith to apply each power to its corresponding element in the list, like so:
zipWith ($) powers [1,2,3] -- returns [1,4,27]
The ($) applies its left (first) argument to its right (second) argument.
Note that using powers as defined here will limit the length of the returned list to 4. If you want to be able to use arbitrary length lists, you want to make powers an infinite list, like so:
powers = [(^y) | y <- [1..]]
Of course, as dave4420 points out, a simpler technique is to simply use
zipWith (^) [1,2,3] [1..] -- returns [1,4,27]
Your match is the standard function map by another name. You need to use zipWith instead (which you can think of as mapping over two lists side-by-side).
Is this homework?
You are currently creating a list for every input value.
What you need to do is recursively compute the appropriate
power for each input value, like this:
match f [] = []
match f (x:xs) y = (f x y) : (match f xs y+1)
Then, you can call this as match pow [1, 2, 3] 1.
This is equivalent to using zipWith and providing the desired function (pow), your input list ([1, 2, 3]) and the exponent list (a lazy one to infinity list) as arguments.

Resources