Is it possible to use map with a function that takes multiple arguments?
I want to use map's second and third arguments repeatedly as the function's arguments.
As in
mapF x y z = map (f y z) [1, 2, 3]
So it'll evaluate f with the same y and z values, but with x = 1, x = 2, x = 3 and so on.
You should use a lambda function, to see this works lets start by using a helper function to map f over some list.
map helper [1, 2, 3] where
helper x = f x y z
In Haskell there are two syntax for functions so lets use the lambda syntax to define our helper function:
map helper [1, 2, 3] where
helper = \x -> f x y z
using the lambda syntax we don't need to give our helper function an explicit name, it can just be an anonymous function we map over the input
map (\x -> f x y z) [1, 2, 3]
So now you can say
mapF y z = map (\x -> f x y z) [1,2,3]
But presumably you don't want x to be 1, 2 and 3, you want it to be a list
you pass as an argument to mapF. So you need to give that a different name:
mapF xs y z = map (\x -> f x y z) xs
It is Haskell convention to use s as a suffix for variables that hold lists or other containers. So if one value is x then a list of them is xs
There are guaranteed to be better ways to do this (still learning) but you can:
f' = map f [1,2,3]
f' is now a list of partially applied f
g y z= map (\h -> h y z) f'
will take each of those functions and run it on the arguments y z.
You can hack that all in one line.
Related
I'm self-learning SML and am currently am stuck with the concept of recursion between two lists of varying sizes.
Suppose you have two int lists of varying size, and a function that multiplies two numbers, like so:
val mul = fn(a, b) => a * b;
I want to use this function to be passed as a parameter into another function, which multiplies the numbers in the same index recursively until at least one of the lists is empty. So
val list1 = [1, 3, 5, 7];
val list2 = [2, 6, 3];
would be passed through that same function with mul and 35 would be returned, as 1*2 + 3*6 + 5*3 would be calculated.
My knowledge of how SML works is a bit limited, as I'm not exactly sure how to carry the result of the sum forward during the recursion, nor how to handle the base case when one of either lists terminates early. Could someone point me in the right direction in thinking of this problem?
You can use pattern-matching and recursion to operate over two lists simultaneously. You then need an accumulator to pass the sum along.
fun mulAndSum acc ([], []) = ...
| mulAndSum acc ([], _) = ...
| mulAndSum acc (_, []) = ...
| mulAndSum acc ((x::xs), (y::ys)) = mulAndSum (...) (xs, ys)
Then when you call the function, you provide zero as the initial state of the accumulator.
mulAndSum 0 ([1, 3, 5, 7], [2, 4, 6])
To add to Chris' answer, recursion over two lists at once can also be achieved with map and zip which are higher-order list combinators (i.e. functions that take another function as argument and operate on lists):
fun add (x, y) = x + y
fun mul (x, y) = x * y
fun sum xs = foldl add 0 xs
val zip = ListPair.zip
fun mulAndSum xs ys = sum (map mul (zip xs ys))
zip will also throw away elements if one of its input lists is longer than the other.
I have an SML assignment, and the general idea is that I shouldn't store state info, should not used built in library functions, etc and just solve in a functional way. Not sure how to do it:
The question requires comparing every element of two lists together:
input
list1: [(3,3,5),(5,4,7),(2,3,4)];
list2: [3, 6];
output
newList: [(3,3,5), (2,3,5)]
Essentially, when the second element in list1's tuple arg matches an item in list 2, then I should add the list1 item to the new output list.
The way I went about implementing it:
fun thing(x, y) =
if null x then []
else if #2 (hd x) = (hd y) then hd x # thing(tl x, y)
else thing(tl x, y);
Obviously the issue with this is that I lose state information: how would you match every element in list1 against every element in list2?
when the second element in list1's tuple arg matches an item in list 2,
then I should add the list1 item to the new output list.
fun thing(x, y) =
if null x then []
else if #2 (hd x) = (hd y) then hd x # thing(tl x, y)
else thing(tl x, y);
Instead of if null x then ..., hd x and tl x, use pattern matching:
fun thing ([], _) = ...
| thing ((x,y,z)::haystack, needles) = ...
To find out if y is a member of needles, build a membership function:
fun elem (p, []) = false
| elem (p, q::qs) = p = q orelse elem (p, qs)
Check if elem (y, needles) to determine whether to include (x,y,z) as part of your result.
Apply thing recursively to haystack and needles.
Compose the recursive result using the :: (cons) operator rather than # (append).
Here's how one could solve this exercise with library functions:
fun curry f x y = f (x, y)
fun thing (haystack, needles) =
List.filter (fn (x,y,z) =>
List.exists (curry op= y) needles) haystack
Can someone help me understand how this function in Haskell works?
f :: Eq t => t -> [t] -> [t]
f x [] = []
f x (y: ys) | (x==y) = [x]
f x (y: ys) | otherwise = y : f x ys
My understanding so far is that the function f tests the equality of variable t and list of type t and returns a list of type t.
If passed x and an empty set f will return an empty set.
If passed x and a list where y heads the list or x is equal to y then it will return a list containing x.
If passed x and a list where y heads the list or anything else then it will return a list headed by y and the contents of the list returned from a recursive call to f using x and list ys?
Is that correct?
Secondly I don't know what the equality being tested is? Is it testing to see if x is contained within a listor checking to see if x is heading the list?
Can someone explain please?
Probably better to pay attention to the terminal cases. Empty list being one and head of list equals to the given element the other. Otherwise, it's going to recursively operate until one of the two cases happens.
By hand go over what will be the returned list for these two
f 3 [1,2]
and
f 3 [1,2,3,4,5]
It's better to discover yourself but I guess you're not there yet.
For
f 3 [1,2] = 1: (f 3 [2]) = 1: 2: (f 3 []) = [1,2]
other one similarly
f 3 [1..5] = 1: (f 3 [2..5]) = 1: 2: (f 3 [3,4,5]) = 1: 2: [3] = [1,2,3]
I need to write a pipe function in OCaml such that pipe [f1;...;fn] (where f1,...,fn are functions!) returns a function f such that for any x, f x computes fn(...(f2(f1 x))).
I need to write it using List.fold_left and need to fill in the parameter of the function
let pipe fs =
let f a x = "fill in this part" in
let base = fun x ->x in
List.fold_left f base fs;;
I already filled in the base. If the first parameter to pipe is an empty list, it returns the second parameter. Ex: pipe [] 3 = 3.
i know for the let f a x part I want to perform function x of the accumulated functions a.
I'm just not sure how to write that. I wrote let f a x = x a but that gave me an error when i tested
pipe [(fun x -> x+x); (fun x -> x + 3)] 3
it should run x+x on 3 then run x+3 on the result and give me 9 but it gave it a type error when i tried to use let f a x = x a
for the fill in part
# let _ = pipe [(fun x -> x+x); (fun x -> x + 3)] 3;;
File "", line 1, characters 24-25:
Error: This expression has type 'a -> 'a
but an expression was expected of type int
What is the correct format to create a function that takes in 2 functions and runs them on each other. Ex: make a function that takes in functions a and b and runs b on the result of a.
To evaluate (fold_left g init fs) x:
when fs is empty, (fold_left g init fs) x = init x. In your case, you want it to be x.
when fs = fs' # [fn]: according to what you would like to be true, the expression should evaluate to
fn (fold_left g init fs' x) but using the definition of fold_left it evaluates also to (g (fold_left g init fs') fn) x.
Hence if the following equations are true:
init x = x
(g k f) x = f (k x)
the problem is solved. Hence, let us define init = fun x -> x and
g k f = fun x -> f (k x).
Well, base is a function like this fun x -> ....
Similarly, your function f needs to return a function, so assume it returns something that looks like this:
fun z -> ...
You have to figure out what this function should be doing with its argument z.
figured it out just needed that z in there for a and x to call
I have a bit of homework to do and I am a complete newbie to Haskell. The question I am having trouble with is to write a function which when given an integer x and a list of integers apply (x-y)*(x-y) to each element in the list and output the new list, with y being each element of the input list.
I have a very rough idea I will have to use the map function but I'm unsure how to go about it.
I have been looking at examples for squaring each element in a list and kind of understand how that works, but how I would implement the (x-y)*(x-y) with y being the current element completely baffles me.
squares :: [Int] -> [Int]
squares (x:xs) = x * x : squares xs
squares [] = []
the exact question I have been set is,
Write a function rela which takes as arguments an integer x and a list of integers. It returns a similar list, but where each element y has been replaced by (x-y)*(x-y), e.g.
Main> rela 2 [3,5,7]
[1,9,25]
I have managed to get it working after reading through some books, but the code I have made misses out the first element in the list. Any explanation why?
equation1 :: Int -> Int -> Int
equation1 x y = (x-y)*(x-y)
rela :: Int -> [Int] -> [Int]
rela x [] =[]
rela x (y:ys) = [ equation1 x y | y <- ys ]
First of all, you should probably create a separate function that does what you want.
e.g.
f x y = (x-y)*(x-y)
Now, every time you create a function in Haskell with multiple parameters, it actually "curries" the function, which means that you get a new function when you apply the first argument to it.
So, you would get a new function by doing this
g = f 5
The expression f 5 is actually a function
And you can apply a number to 'g' and x will always be '5'
So if we want to create a function that takes two parameters, 'x' and 'y', and applies (x-y)*(x-y) to a list where y is the current element, then all we need to do is the following:
f x y = (x-y)*(x-y)
squareDifference x = map (f x) [1,2,3,4]
Which you can use by calling squareDifference 5 or any other number as an argument
A more general version would allow you to pass in a list as well
squareDifference x xs = map (f x) xs
Which you would call by doing squareDifference 3 [1,2,3]
do you understand lambda functions?
map (\val -> the function) xs
is what you need.
currying is even better, but not as simple.
edit:
more conceptual...
map iterates down a list applying a function.
map (+ 3) xs
uses the currying technique mentioned above. you could also:
map (\x -> x + 3) xs
to accomplish the same thing.
Simple example:
rela :: Int -> [Int] -> [Int]
rela x = map (\y -> (x-y)*(x-y))
Or might you want any perversions? -) Here you are with Applicatives:
import Control.Applicative
rela :: Int -> [Int] -> [Int]
rela x = map $ (*) <$> (x-) <*> (x-)
Hello I guess you mean this:
Prelude> let rela n = map (\ x -> (x - n)^2)
Prelude> rela 2 [3,5,7]
[1,9,25]