I'm writting a recursive function that use specific formulas to calculate 2 lists.
But I will simplify the function so you can understand the problem I'm having because the point here is to detect [] of the list.
So I've the following code:
listSum::([Integer],[Integer])->Double
listSum ((x:xs),(y:ys))
| ((x:xs),(y:ys))==(x:[],y:[])=0.0
| otherwise = (((fromIntegral x)::Double)+((fromIntegral y)::Double)) + listSum ((xs),(ys))
Output I'm having right now
listSum([1,2],[1,2])
2.0
listSum([1],[1])
0.0
listSum([],[])
*** Exception: file.hs: .....: Non-exhaustive patterns in function ListSum
And the output I wish to have
listSum([1,2],[1,2])
6.0
listSum([1],[1])
2.0
listSum([],[])
0.0
What did I miss? Or did I write too much?
You don't need the first guard in your function. You can simply write it as the following (I just dropped ::Double because Haskell can infer it)
listSum :: ([Integer], [Integer]) -> Double
listSum ([], []) = 0.0
listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)
Now, whenever the arguments passed to listSum are empty lists, the result will be 0.0, otherwise the recursive function will be called.
Note: The above function will work only if both the lists are of equal size. Otherwise, you need to write it like this
listSum::([Integer],[Integer])->Double
listSum ([], []) = 0.0
listSum ((x:xs), []) = fromIntegral x + listSum(xs, [])
listSum ([], (y:ys)) = fromIntegral y + listSum(ys, [])
listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)
Note: Even simpler, the entire code can be written, as suggested by Rein Henrichs, like this
pairwiseSum xs ys = sum (zipWith (+) xs ys)
Related
I have a function called zip_with_2_fs. I am trying to make it tail recursive (zip_with_2_fs_tr) but I don't really understand what I am doing. I am new to Ocaml and would like to develop a deeper understanding of tail recursion and helper functions.
let rec zip_with_2_fs fx fy xs ys =
match (xs, ys) with
| ([], []) -> []
| ([], _) -> []
| (_, []) -> []
| (xh::xt, yh::yt) -> (fx xh, fy yh)::zip_with_2_fs fx fy xt yt;;
How would I go about fixing this?
let zip_with_2_fs_tr fx fy xs ys =
let rec helper fxx fy xss yss =
match (xs, ys) with
| ([], []) -> []
| ([], _) -> []
| (_, []) -> []
| (xh::xt, yh::yt) -> (fx xh, fy yh)::helper fx fy xt yt
in helper fx fy xs ys;;
The expression, (fx xh, fy yh)::helper fx fy xt yt is not tail recursive, because in order to reduce it to a value you need the result of the recursive call. E.g., let's rewrite it in a more verbose way, just to give names to things (it is easier to speak about things when they have names),
let head = (fx xh, fy yh) in
let tail = helper fx fy xt yt in (* recursive call *)
let result = head :: tail in
result
So here, we are making a recursive call and the result of the current call is not determined until this call returns, therefore our calls accumulate (as the recursive call will make its own call and wait until the result is ready, and so on) and we have precious stack space being spent to store all those intermediate results.
So the trick is that a value returned by the recursive call shall be the result of the calling function. The concept of a tail call is actually more general that the tail-recursive call. As any call whose result becomes the result of a caller is called a tail call and could be made without expending the stack space, e.g., speaking C,
int bar(int x) {return x + 1; }
int foo(int x) {return bar(x+1);}
Here we have a tail-call from foo to bar and the compiler may easily implement it with just a jump to bar without having to allocate a new stack frame or taking care of passing the value retuned from bar.
Back to OCaml. So we need to make sure that the value returned by our recursive function is the value returned by the recursive call. But there is no free lunch here, since we need to have some space where we will accumulate our intermediate result. In the non-tail recursive function version it was the program stack. Instead of the program stack, we can explicitly create a value and accumulate values in it during our recursive calls, e.g.,
let zip_with_f_fs fx fy xs ys =
let rec loop acc xs ys = match xs, ys with
| [],[] -> List.rev acc
| x::xs,y::ys -> loop ((fx x, fy y)::acc) xs ys
| _ -> failwith "uneven lists" in
loop [] xs ys
Now you can see that we have a recursive call to loop
| x::xs,y::ys -> loop ((fx x, fy y)::acc) xs ys
that is in the tail position, and we store our result in the first parameter called acc and once we reach the end of both lists, we reverse it (because we were pretending it, in fact acc was our stack) to get the values in the right order.
Implementing Haskell's take and drop functions using foldl.
Any suggestions on how to implement take and drop functions using foldl ??
take x ls = foldl ???
drop x ls = foldl ???
i've tried these but it's showing errors:
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func x y | (length y) > n = x : y
| otherwise = y
ERROR PRODUCED :
*** Expression : foldl func [] list
*** Term : func
*** Type : a -> [a] -> [a]
*** Does not match : [a] -> [a] -> [a]
*** Because : unification would give infinite type
Can't be done.
Left fold necessarily diverges on infinite lists, but take n does not. This is so because left fold is tail recursive, so it must scan through the whole input list before it can start the processing.
With the right fold, it's
ntake :: Int -> [a] -> [a]
ntake 0 _ = []
ntake n xs = foldr g z xs 0
where
g x r i | i>=n = []
| otherwise = x : r (i+1)
z _ = []
ndrop :: Int -> [a] -> [a]
ndrop 0 xs = xs
ndrop n xs = foldr g z xs 0 xs
where
g x r i xs#(_:t) | i>=n = xs
| otherwise = r (i+1) t
z _ _ = []
ndrop implements a paramorphism nicely and faithfully, up to the order of arguments to the reducer function g, giving it access to both the current element x and the current list node xs (such that xs == (x:t)) as well as the recursive result r. A catamorphism's reducer has access only to x and r.
Folds usually encode catamorphisms, but this shows that right fold can be used to code up a paramorphism just as well. It's universal that way. I think it is beautiful.
As for the type error, to fix it just switch the arguments to your func:
func y x | ..... = .......
The accumulator in the left fold comes as the first argument to the reducer function.
If you really want it done with the left fold, and if you're really sure the lists are finite, two options:
ltake n xs = post $ foldl' g (0,id) xs
where
g (i,f) x | i < n = (i+1, f . (x:))
| otherwise = (i,f)
post (_,f) = f []
rltake n xs = foldl' g id xs r n
where
g acc x = acc . f x
f x r i | i > 0 = x : r (i-1)
| otherwise = []
r _ = []
The first counts from the left straight up, potentially stopping assembling the prefix in the middle of the full list traversal that it does carry to the end nevertheless, being a left fold.
The second also traverses the list in full turning it into a right fold which then gets to work counting down from the left again, being able to actually stop working as soon as the prefix is assembled.
Implementing drop this way is bound to be (?) even clunkier. Could be a nice exercise.
I note that you never specified the fold had to be over the supplied list. So, one approach that meets the letter of your question, though probably not the spirit, is:
sillytake :: Int -> [a] -> [a]
sillytake n xs = foldl go (const []) [1..n] xs
where go f _ (x:xs) = x : f xs
go _ _ [] = []
sillydrop :: Int -> [a] -> [a]
sillydrop n xs = foldl go id [1..n] xs
where go f _ (_:xs) = f xs
go _ _ [] = []
These each use left folds, but over the list of numbers [1..n] -- the numbers themselves are ignored, and the list is just used for its length to build a custom take n or drop n function for the given n. This function is then applied to the original supplied list xs.
These versions work fine on infinite lists:
> sillytake 5 $ sillydrop 5 $ [1..]
[6,7,8,9,10]
Will Ness showed a nice way to implement take with foldr. The least repulsive way to implement drop with foldr is this:
drop n0 xs0 = foldr go stop xs0 n0
where
stop _ = []
go x r n
| n <= 0 = x : r 0
| otherwise = r (n - 1)
Take the efficiency loss and rebuild the whole list if you have no choice! Better to drive a nail in with a screwdriver than drive a screw in with a hammer.
Both ways are horrible. But this one helps you understand how folds can be used to structure functions and what their limits are.
Folds just aren't the right tools for implementing drop; a paramorphism is the right tool.
You are not too far. Here are a pair of fixes.
First, note that func is passed the accumulator first (i.e. a list of a, in your case) and then the list element (an a). So, you need to swap the order of the arguments of func.
Then, if we want to mimic take, we need to add x when the length y is less than n, not greater!
So we get
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func y x | (length y) < n = x : y
| otherwise = y
Test:
> myFunc 5 [1..10]
[5,4,3,2,1]
As you can see, this is reversing the string. This is because we add x at the front (x:y) instead of at the back (y++[x]). Or, alternatively, one could use reverse (foldl ....) to fix the order at the end.
Also, since foldl always scans the whole input list, myFunc 3 [1..1000000000] will take a lot of time, and myFunc 3 [1..] will fail to terminate. Using foldr would be much better.
drop is more tricky to do. I don't think you can easily do that without some post-processing like myFunc n xs = fst (foldl ...) or making foldl return a function which you immediately call (which is also a kind of post-processing).
So I am currently trying to figure out how to write a function where it takes 2 lists of equal lengths and multiplies the same position of both lists through folding, and returns the result as a new List.
eg) let prodList [1; 2; 3] [4; 5; 6] ;;
==> (through folding) ==> [1*4; 2*5; 3*6]
==> result = [4; 10; 18]
I feel like I need to use List.combine, since it will put the values that need to be multiplied into tuples. After that, I can't figure out how to break apart the tuple in a way that allows me to multiply the values. Here is what I have so far:
let prodLists l1 l2 =
let f a x = (List.hd(x)) :: a in
let base = [] in
let args = List.rev (List.combine l1 l2) in
List.fold_left f base args
Am I on the right track?
You can use fold_left2 which folds two lists of the same length. The documentation can give you more details (https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
List.fold_left2 f a [b1; ...; bn] [c1; ...; cn] is f (... (f (f a b1 c1) b2 c2) ...) bn cn. Raise Invalid_argument if the two lists are determined to have different lengths.
Another way is to fold the output of combine as you have suggested, I would recommend you to try it by yourself before looking at the solution bellow.
Solution:
let prod_lists l s =
List.rev (List.fold_left2 (fun acc a b -> (a * b) :: acc) [] l s);;
let prod_lists' l s =
List.fold_left (fun acc (a, b) -> (a * b) :: acc) [] (List.rev (List.combine l s));;
First let me note using fold to implement this operation seems a bit forced, since you have to traverse both lists at the same time. Fold however combines the elements of a single list. Nonetheless here is an implementation.
let e [] = []
let f x hxs (y::ys) = (x*y) :: hxs ys
let prodList xs ys = List.fold_right f xs e ys
Looks a bit complicated, so let me explain.
Universal Property of fold right
First you should be aware of the following property of fold_right.
h xs = fold_right f xs e
if and only if
h [] = e
h (x::xs) = f x (h xs)
This means that if we write the multiplication of lists in the recursive form below, then we can use the e and f to write it using fold as above. Note though we are operating two lists so h takes two arguments.
Base case - empty lists
Multiplying two empty lists returns an empty list.
h [] [] = []
How to write this in the form above? Just abstract over the second argument.
h [] = fun [] -> []
So,
e = fun [] -> []`
Or equivalently,
e [] = []
Recursive case - non-empty lists
h (x::xs) (y::ys) = x*y :: h xs ys
Or, using just one argument,
h (x::xs) = fun -> (y::ys) -> x*y :: h xs ys
Now we need to rewrite this expression in the form h (x::xs) = f x (h xs). It may seem complicated but we just need to abstract over x and h xs.
h (x::xs) = (fun x hxs -> fun (y::ys) -> x*y :: hxs ys) x (h xs)
so we have that f is defined by,
f = fun x hxs -> fun (y::ys) -> x*y :: hxs ys
or equivalently,
f x hxs (y::ys) = x*y :: hxs ys
Solution as a fold right
Having determined both e and f we just plug then into fold according to the first equation of the property above. And we get,
h xs = List.fold_right f xs e
or equivalently,
h xs ys = List.fold_right f xs e ys
Understanding the implementation
Note that the type of List.fold_right f xs e is int list -> int list, so the fold is building a function on lists, that given some ys will multiply it with the given parameter xs.
For an empty xs you will expect an empty ys and return an empty result so,
e [] = fun [] -> []
As for the recursive case, the function f in a fold_right must implement a solution for x::xs from a solution for xs. So f takes an x of type int and a function hxs of type int list -> int list which implements the multiplication for the tail, and it must implement multiplication for x::xs.
f x hxs = fun (y::ys) -> x*y :: hxs ys
So f constructs a function that multiplies x with y, and then applies to ys the already constructed hxs which multiplies xs to a list.
You mostly have the right idea; you'll want to combine (zip in other languages) the two lists and then map over each tuple:
let prod_lists l1 l2 =
List.combine l1 l2
|> List.map (fun (a, b) -> a * b)
The key is that you can pattern match on that tuple using (a, b).
You can also fold over the combined list, then rev the result, if you don't want to use map.
I'm writing a small program that takes coefficients of two polynomials and FOILs them together, however I can only seem to multiply elements at the same indices.
fun polyMult([],[]) = []
| polyMult(M, []) = []
| polyMult([], N) = []
| polyMult(M as x::xs, N as y::ys) =
(x * y) :: polyMult(M, ys);
I can successfully multiply the first element of M by every element of N, but then afterwards I want to be able to advance one element in M and then take that and multiply it by every element in N.
Is there any way I can advance the index in M and repeat the multiplication process? I.E
polyMult(tl(M) as x::xs, N as y::ys) =
(x * y) :: polyMult(M, ys);
Something along these lines
fun foldL F y nil = y
| foldL F y (x::xr) = foldL F (F(x,y)) xr;
fun polymult(M, nil) = nil
| polymult(nil, N) = nil
| polymult(m::mr, N) = foldL(fn(x,a) => x * a) m N::polymult(mr,N);
But you will need to figure out how to make it only accept real numbers and not integers as it does now ;)
I want to write a function rotate n l that returns a new list containing the same elements as l, "rotated" n times to the right. For example,
rotate 0 [1;2;3;4] should return [1;2;3;4]
rotate 1 [1;2;3;4] should return [4;1;2;3]
rotate 2 [1;2;3;4] should return [3;4;1;2]
rotate 3 [1;2;3;4] should return [2;3;4;1]
rotate 4 [1;2;3;4] should return [1;2;3;4]
etc.
The behavior of rotate n for n less than 0 should be the same as for n equal to 0.
I want to write this without using the list concatenation operator # from Pervasives.
Update: Here is the rotation function I wrote:
let rot1 l =
let rec iterate acc = function
[] -> []
| [x] -> x :: List.rev acc
| x :: l -> iterate (x :: acc) l
in
iterate [] l;;
But I want it to do the same thing without using List.rev.
Is there a way to do this?
Agree with Jeffrey, show us what you tried. Here's a small hint in case you need to get started. If you can write a function that performs only 1 rotation i.e. equivalent to rotate 1 l. (I call it one_rot). Then rotate can be easily defined as:
let rec rotate n l =
match n with
| 0 -> l
| _ -> rotate (n-1) (one_rot l)
Your solution is perfectly fine for me. Not sure what you have against List.rev but here's a completely stand alone one_rot. Note that we have to sacrifice tail recursion. You could probably make this quite a bit shorter too:
let rec last = function
| [] -> assert false
| [x] -> x
| x::xs -> last xs
let rec init = function
| [] -> []
| [x] -> []
| x::xs -> x::(init xs)
let one_rot l = (last l)::(init l)
This problem can be solved by combining these 3 functions:
cat(skip(list, places), take(list, places))
The implementation looks like:
let rec cat = function
([], y) -> y
| (x::xs, y) -> x :: cat (xs, y)
let rec skip = function
([], _) -> []
| (_::xs as xs1, c) -> if c > 0 then skip(xs, c - 1) else xs1
let rec take = function
([], _) -> []
| (x::xs, c) -> if c > 0 then x :: take(xs, c - 1) else []
let cycle l i =
cat (skip (l, i), take (l, i))
cycle ([1;2;3;4;5;6], 3);;
val it : int list = [4; 5; 6; 1; 2; 3]