Related
I'm currently studying for a CS exam and I'm having an hard time understanding an exercise from my book. The exercise is as follows:
Define, using FOLDR and without using explicit recursion, a function (split : ’a list -> ’a -> ’a list * ’a list) such that split l n returns a pair of lists. The first contains all the values preceding the first occurrence of n in l (in the same order), and the second contains all the remaining elements (in the same order). If n does not appear in l, there are no values preceding the first occurrence of n.
Examples: split [3;-5;1;0;1;-8;0;3] 0 = ([3;-5;1],[0;1;-8;0;3]), split [3;4;5] 7 = ([],[3;4;5])
This is the code written by my professor to solve the exercise:
let split l n =
let f x (l1, l2, b) =
if x = n then ([], x::(l1#l2), true)
else if b then (x::l1, l2, b)
else (l1, x::l2, b)
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
I don’t understand that second line at all (let f x (l1, l2, b)).
How do those parameters get filled with a value, so that all the logic that comes with it makes sense? For example: what is x and how can it be compared to n if it has no value? What is the meaning of those Boolean values in b?
In addition I don't understand that foldr function in the last line and I don't find any documentation about it. In fact, even my compiler doesn’t understand what foldr is and gives me an error (*Unbound value foldr*). Initially I thought it was some kind of abbreviation for List.fold_right but if I try to replace with the latter I still get an error because the following parameters are not correct (File "split.ml", line 6, characters 41-56:
Error: This expression has type 'a * 'b * 'c
but an expression was expected of type 'd list).
Thank you in advance for any help or advice.
I don't know whether this is allowed by OCAML's syntax rules or not, but let's add some extra white space to make it clearer:
let split l n =
let f x ( l1, l2 , b ) =
if x = n then ( [], x::(l1#l2), true )
else if b then (x::l1, l2 , b ) (* b is true *)
else ( l1, x:: l2 , b ) (* b is false *)
in let (l1, l2, b) = foldr f ( [], [] , false) l
in (l1, l2) ;;
foldr is, in pseudocode,
foldr f z [x1 ; x2 ; ... ; xn1 ; xn ]
=
x1 -f- (x2 -f- (... -f- (xn1 -f- (xn -f- z))...))
where a -f- b denotes simple application f a b, just written infix for convenience. In other words,
foldr f z [x1 ; x2 ; ... ; xn1 ; xn] (* x_{n-1} *)
=
f x1 (foldr f z [x2 ; ... ; xn1 ; xn]) (* x_{n-1} *)
whereas
foldr f z [] = z
Thus the above is actually equivalent to
= let t1 = f xn z
in let t2 = f xn1 t1 (* x_{n-1} *)
in ....
in let tn1 = f x2 tn2 (* t_{n-2} *)
in let tn = f x1 tn1 (* t_{n-1} *)
in tn
You should now be able to see that what this does is to work on the list's elements from right to left, passing interim results to the subsequent applications of f on the left.
You should also be able now to write that missing definition of foldr yourself.
So if we substitute your specific definition of f, how it works for a list of e.g. three elements [x1; x2; x3] where x2 = n, is equivalent to
let (l1, l2, b ) = ( [], [] , false)
in let (l1_3, l2_3, b_3) = ( l1, x3::l2 , b )
in let (l1_2, l2_2, b_2) = ( [], x2::(l1_3#l2_3) , true )
in let (l1_1, l2_1, b_1) = (x1::l1_2, l2_2 , b_2 )
in (l1_1, l2_1)
i.e.
let (l1, l2, b ) = ( [], [] , false)
in let (l1_3, l2_3, b_3) = ( [], x3::[] , false)
in let (l1_2, l2_2, b_2) = ( [], x2::([]#[x3]) , true )
in let (l1_1, l2_1, b_1) = (x1::[], [x2 ; x3] , true )
in ([x1], [x2; x3])
Thus the resulting lists are being built from the back.
The Boolean flags being passed along allows the function to correctly handle cases where there are more than one elements equal to n in the list. The same effect can be achieved without any flags, with a small post-processing step instead, as
let split l n =
let f x ( l1, l2 ) =
if x = n then ( [], x::(l1#l2))
else (x::l1, l2 )
in match foldr f ( [], [] ) l with
| (l1, []) -> ([], l1)
| (l1, l2) -> (l1, l2) ;;
(if that's not a valid OCaml code, take it as a pseudocode then).
If you use the List.fold_right then this will work.
let split l n =
let f x (l1, l2, b) =
if x = n
then
([], x::(l1#l2), true)
else if b
then
(x::l1, l2, b)
else
(l1, x::l2, b)
in let (l1, l2, b) = List.fold_right f l ([], [], false)
in (l1, l2)
Fellow CS Major here.
let f x (l1, l2, b)
defines a function, which takes two arguments one called x and one is a tripple of 3 arguments (l1, l2, b). This function has it's scope limited to the following line
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
The part you are probably struggling with is the keyword "in" which limits the scope of one expression to the next one. so exp1 in exp2 limits the scope of expression one to expression two.
Also, x and (l1, l2, b) stand for arbitrary parameters only valid in the function body. Look at which parameters foldr takes (the first one should be a function that has the same parameters as the function f your professor defined). This foldr function then assigns a value to x (and (l1, l2, b)) in the context of foldr.
let f x (l1, l2, b)
....
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
While (l1, l2, b) in the first line is not the same as (l1, l2, b) in the third line (of the snippet above), here
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
l1 and l2 are the same (in let (l1, l2, b) and in (l1, l2)).
PS: You need to define the foldr function (either import it or maybe your professor has some definition on the exercise sheet that you can copy).
In Haskell a list is given, but you should reverse every even element. For example the list
f ["rehtruF", "dooG", kcuL"]
should be changed into
["Further", "Good" "Luck"]
We tried this function:
f [] = []
f [x] = []
f (xs:ys:xss) = (reverse xs):(f xss)
but unfortunately, it only reversed the first element and prints it out. Do you have any idea how we could change the code, so that every even element is reserved and the output is as demonstrated above?
TL;DR - this is the solution (based on this answer) that Thomas M. DuBuisson alluded to in his comment. Oops.
You don't even need to explicitly iterate over the input. Imagine you had a list of functions fs = [f0, f1, f2, ...] and a list of values xs = [x0, x1, x2, ...], and you want to get [f0 x0, f1 x1, f2 x2, ...]. You do that with zipWith ($):
zipWith ($) fs xs -- == [f0 $ x0, f1 $ x1, f2 $ x2, ...]
-- == [f0 x0, f1 x1, f2 x2, ...]
For your problem, your fs would be an alternating sequence of reverse and id, which you can produce with cycle [reverse, id] == [reverse, id, reverse, id, ...]
Putting this together,
f :: [String] -> [String]
f strings = zipWith ($) (cycle [reverse, id]) strings
-- == [reverse strings0, id strings0, reverse strings2, id strings3, ...]
or simply
f :: [String] -> [String]
f = zipWith ($) (cycle [reverse, id])
The problem is that you completely drop the ys element. What you actually want is keep it as-is, i.e. put it as-is in the result list.
f (xs:ys:xss) = reverse xs : ys : f xss
Note that GHC would have warned you about the unused ys binding, if you had turned on the -Wall option (which is generally a good idea for beginners). You can do that by executing the compiler/interpreter with ghc -Wall YOURFILE.hs, or by typing :set -Wall in a GHCi session.
To reverse the even elements in the list, the first thing is to find even elements, one of the ways to do that is to index each elements in the list firstly like:
zip [0..] xs
and then, we reverse the elements has even index:
if index `mod` 2 == 0 then reverse x else x
put them all as
f xs = map reverseEven (zip [0..] xs)
where reverseEven (index, x) = if index `mod` 2 == 0
then reverse x else x
If you add an extra variable, you can keep track if you are on an even element or an odd element. For example, here we are using 1 to mean odd and 0 to mean even:
f = f' 1
where
f' _ [] = []
f' 1 (x:xs) = reverse x: f' 0 xs
f' 0 (x:xs) = x: f' 1 xs
One ought not to calculate anything that doesn't need calculating. No zipping, no cycling, no mod taking, just pure function calling:
foo :: [[a]] -> [[a]]
foo xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
((:) . reverse)
(:)
First element is considered to be at index 0, i.e. at even position, as is in the question.
> foo ["Further","Good","Luck"]
["rehtruF","Good","kcuL"]
> foo $ foo ["Further","Good","Luck"]
["Further","Good","Luck"]
With plain recursion, what the above foldr-based definition is doing is:
foo = f where
f (x:xs) = reverse x : g xs
g (x:xs) = x : f xs
, plus the obvious []-handling cases.
With foldr, [] is checked for by foldr itself; with mutual recursion, it must be done by each of the two cooperating functions.
So what I have so far is something like this:
combs :: [[Char]]
combs = [[i] ++ [j] ++ [k] ++ [l] | i <- x, j <- x, k <- x, l <- x]
where x = "abc"
So this is the working function for n = 4, is there any way to make this work for an arbitrary number of generators? I could program in for n = 1, 2, 3 etc.. but ideally need it to work for any given n. For reference, x is just an arbitrary string of unique characters. I'm struggling to think of a way to somehow extract it to work for n generators.
You can use replicateM:
replicateM :: Applicative m => Int -> m a -> m [a]
E.g.:
generate :: Num a => Int -> [[a]]
generate = flip replicateM [1,2,3]
to generate all possiible lists of a given length and consisting of elements 1..3.
As far as I know, you can not construct list comprehension with an arbitrary number of generators, but usually if you do something with arbitrary depth, recursion is the way to do it.
So we have to think of solving this, in terms of itself. If you want all possible strings that can be generated with the characters in x. In case n = 0, we can generate exactly one string: the empty string.
combs 0 = [""]
so a list with one element [].
Now in case we want to generate strings with one characters, we can of course simply return x:
combs 1 = x
and now the question is what to do in case n > 1. In that case we can obtain all the strings with length n-1, and and for each such string, and each such character in x, produce a new string. Like:
combs n = [ (c:cs) | c <- x, cs <- combs (n-1) ]
Note that this makes the second case (n = 1) redundant. We can pick a character c from x, and prepend that to the empty string. So a basic implementation is:
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = [(c:cs) | c <- x, cs <- combs (n-1)]
where x = "abc"
Now we can still look for improvements. List comprehensions are basically syntactical sugar for the list monad. So we can use liftA2 here:
import Control.Applicative(liftA2)
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = liftA2 (:) x (combs (n-1))
where x = "abc"
we probably also want to make the set of characters a parameter:
import Control.Applicative(liftA2)
combs :: [Char] -> Int -> [[Char]]
combs _ 0 = [""]
combs x n = liftA2 (:) x (combs (n-1))
and we do not have to restrict us to characters, we can produce a certesian power for all possible types:
import Control.Applicative(liftA2)
combs :: [a] -> Int -> [[a]]
combs _ 0 = [[]]
combs x n = liftA2 (:) x (combs (n-1))
First I would translate the comprehension as a monadic expression.
x >>= \i -> x >>= \j -> x >>= \k -> x >>= \l -> return [i,j,k,l]
With n = 4 we see we have 4 x's, and generally will have n x's. Therefore, I am thinking about a list of x's of length n.
[x,x,x,x] :: [[a]]
How might we go from [x,x,x,x] to the monadic expression? A first good guess is foldr, since we want to do something with each element of the list. Particularly, we want to take an element from each x and form a list with these elements.
foldr :: (a -> b -> b) -> b -> [a] -> b
-- Or more accurately for our scenario:
foldr :: ([a] -> [[a]] -> [[a]]) -> [[a]] -> [[a]] -> [[a]]
There are two terms to come up with for foldr, which I will call f :: [a] -> [[a]] -> [[a]] and z :: [[a]]. We know what foldr f z [x,x,x,x] is:
foldr f z [x,x,x,x] = f x (f x (f x (f x z)))
If we add parentheses to the earlier monadic expression, we have this:
x >>= \i -> (x >>= \j -> (x >>= \k -> (x >>= \l -> return [i,j,k,l])))
You can see how the two expressions are looking similar. We should be able to find an f and z to make them the same. If we choose f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we get:
f x (f x (f x (f x z)))
= (\x a -> a >>= \a' -> x >>= \x' -> return (x' : a')) x (f x (f x (f x z)))
= f x (f x (f x z)) >>= \a' -> x >>= \x' -> return (x' : a')
= f x (f x (f x z)) >>= \a' -> x >>= \l -> return (l : a')
= (f x (f x z) >>= \a' -> x >>= \k -> return (k : a')) >>= \a' -> x >>= \l -> return (l : a')
= f x (f x z) >>= \a' -> x >>= \k -> x >>= \l -> return (l : k : a')
Note that I have reversed the order of i,j,k,l to l,k,j,i but in context of finding combinations, this should be irrelevant. We could try a' ++ [x'] instead if it was really of concern.
The last step is because (a >>= \b -> c) >>= \d -> e is the same as a >>= \b -> c >>= \d -> e (when accounting for variable hygiene) and return a >>= \b -> c is the same as (\b -> c) a.
If we keep unfolding this expression, eventually we will reach z >>= \a' -> … on the front. The only choice that makes sense here then is z = [[]]. This means that foldr f z [] = [[]] which may not be desirable (preferring [] instead). Instead, we might use foldr1 (for non-empty lists, and we might use Data.NonEmpty) or we might add a separate clause for empty lists to combs.
Looking at f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we might realise this helpful equivalence: a >>= \b -> return (c b) = c <$> a. Therefore, f = \x a -> x >>= \x' -> (x' :) <$> a. Then also, a >>= \b -> c (g b) = g <$> a >>= \b -> c and so f = (:) <$> x >>= \x' -> x' <$> a. Finally, a <*> b = a >>= \x -> x <$> b and so f = (:) <$> x <*> a.
The official implementation of sequenceA for lists is foldr (\x a -> (:) <$> x <*> a) (pure []), exactly what we came up with here too. This can be further shortened as foldr (liftA2 (:)) (pure []) but there is possibly some optimisation difference that made the implementors not choose this.
Last step is to merely come up with a list of n x's. This is just replicate replicate n x. There happens to be a function which does both replication and sequencing, called replicateM replicateM n x.
I am trying to define a function that accepts a point (x,y) as input, and returns an infinite list corresponding to recursively calling
P = (u^2 − v^2 + x, 2uv + y)
The initial values of u and v are both 0.
The first call would be
P = (0^2 - 0^2 + 1, 2(0)(0) + 2) = (1,2)
Then that resulting tuple (1,2) would be the next values for u and v, so then it would be
P = (1^2 - 2^2 + 1, 2(1)(2) + 2) = (-2,6)
and so on.
I'm trying to figure out how to code this in Haskell. This is what I have so far:
o :: Num a =>(a,a) -> [(a,a)]
o (x,y) = [(a,b)| (a,b)<- [p(x,y)(x,y)]]
where p(x,y)(u,v) = ((u^2)-(v^2)+x,(2*u*v)+y)
I'm really not sure how to make this work. Any help would be appreciated!
Let's first ignore the exact question you have, and focus on getting the loop working. What you want, essentially, is to have something that takes some initial value iv (namely, (0, 0) for (u, v)), and returns the list
f iv : f (f iv) : f (f (f iv)) : f (f (f (f iv))) : ...
for some function f (constructed from your p and (x, y)). Moreover, you want the result to reuse the previously computed elements of the list. If I would write a function myself that does this, it might looke like this (but maybe with some different names):
looper :: (a -> a) -> a -> [a]
looper f iv = one_result : more_results
where
one_result = f iv
more_results = looper f one_result
But, of course, I would first look if a function with that type exists. It does: it's called Data.List.iterate. The only thing it does wrong is the first element of the list will be iv, but that can be easily fixed by using tail (which is fine here: as long as your iteration function terminates, iterate will always generate an infinite list).
Let's now get back to your case. We established that it'll generally look like this:
o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate f iv)
where
f (u, v) = undefined
iv = undefined
As you indicated, the initial value of (u, v) is (0, 0), so that's what our definition of iv will be. f now has to call p with the (x, y) from o's argument and the (u, v) for that iteration:
o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate f iv)
where
f (u, v) = p (x, y) (u, v)
iv = (0, 0)
p = undefined
It's as simple as that: the (x, y) from o's definition is actually in scope in the where-clause. You could even decide to merge f and p, and end up with
o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate p iv)
where
iv = (0, 0)
p (u, v) = (u^2 - v^2 + x, 2 * u * v + y)
Also, may I suggest that you use Data.Complex for your application? This makes the constraints on a a bit stricter (you need RealFloat a, because of Num.signum), but in my opinion, it makes your code much easier to read:
import Data.Complex
import Data.List (iterate)
{- ... -}
o :: Num (Complex a) => Complex a -> [Complex a]
o c = tail (iterate p iv)
where
iv = 0 -- or "0 :+ 0", if you want to be explicit
p z = z^2 + c
You want:
To construct a list [(u, v)] with the head of this list equal (0, 0)
And then map this list with the function \(u, v) -> (u^2 - v^2 + x, 2 * u * v + y), appending results of this function to the list.
We can write this function as described:
func :: (Num t) => (t, t) -> [(t, t)]
func (x, y) = (0, 0) : map functionP (func (x, y))
where functionP (u, v) = (u^2 - v^2 + x, 2 * u * v + y)
GHCi > take 5 $ func (1, 2)
> [(0,0),(1,2),(-2,6),(-31,-22),(478,1366)]
I have a function
f :: Int -> Int -> Int
and I have a list of arbitrary length but for the sake of the example:
[x1,x2,x3]
I need to apply f to the list such that the resulting list looks like this:
[f x1 x1 + f x1 x2 + f x1 x3 , f x2 x1 + f x2 x2 + f x2 x3 , f x3 x1 + f x3 x2 + f x3 x3]
I know that
map f [x1,x2,x3] will give [f x1, f x2, f x3]
but this doesn't seem like much help here.
What's the best way to do it?
You could use a list comprehension, to illustrate try the following expression under ghci,
fun f xs = map sum [[ f x y | y <- xs] | x <- xs]
A solution without list comprehensions:
Use map twice.
map (\x -> sum $ map (f x) xs) xs
You can use applicative functors to do it this way :
import Control.Applicative
let l = ["a", "b", "c"]
(++) <$> l <*> l
That will return ["aa","ab","ac","ba","bb","bc","ca","cb","cc"].
To explain a little bit further, (++) <$> l will map the function (++) on every element of l, thus returning [("a"++), ("b"++), ("c"++)]. Then, using <*> will apply all of these functions to all of the elements of l.
See the documentation about applicative functors for more details. http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Applicative.html