example
Input: [1..10]
Output: [1,10,2,9,3,8,4,7,5,6,6,5,7,4,8,3,9,2,10,1]
I tried this
fon(x:y:xs) =reverse (x:xs)
fun (x:y:xs) = x : (fon xs)
what about this:
interweave :: [a] -> [a]
interweave zs = f zs (reverse zs)
where f xs ys = concat $ zipWith (\ x y -> [x,y]) xs ys
example
λ> interweave [1..10]
[1,10,2,9,3,8,4,7,5,6,6,5,7,4,8,3,9,2,10,1]
Since this looks like homework, I'll provide a hint.
You need both the original list and the reversed list. Try something like
foo :: [a] -> [a]
foo xs = bar xs (reverse xs)
bar :: [a] -> [a] -> [a]
...
Related
So I'm trying to write a function that, given two lists of integers, adds the ith even number of each list and returns them in another list. In case one of the list doesn't have an ith even number, a 0 is considered. For example, if the lists are [1,2,1,4,6] and [2,2], it returns [4,6,6] ([2+2,4+2,6+0]). I have the following code:
addEven :: [Int] -> [Int] -> [Int]
addEeven [] [] = []
addEeven (x:xs) [] = filter (\g -> g `mod`2 == 0) (x:xs)
addEven [] (y:ys) = filter (\g -> g `mod` 2 == 0) (y:ys)
addEven (x:xs) (y:ys) = (a + b):(addEven as bs)
where
(a:as) = filter (\g -> g `mod` 2 == 0) (x:xs)
(b:bs) = filter (\g -> g `mod` 2 == 0) (y:ys)
When I run that with the previous example, I get:
[4,6*** Exception: ex.hs:(4,1)-(8,101): Non-exhaustive patterns in function addEven
I really can't see what I'm missing, since it doesn't work with any input I throw at it.
A filter might eliminate elements, hence filter (\g -> gmod2 == 0) is not said to return any elements, and thus the patterns (a:as) and (b:bs) might fail.
That being said, I think you make the problem too complex here. You can first define a helper function that adds two elements of a list:
addList :: Num a => [a] -> [a] -> [a]
addList (x:xs) (y:ys) = (x+y) : addList xs ys
addList xs [] = xs
addList [] ys = ys
Then we do the filter on the two parameters, and make a function addEven that looks like:
addEven :: Integral a => [a] -> [a] -> [a]
addEven xs ys = addList (filter even xs) (filter even ys)
or with on :: (b -> b -> c) -> (a -> b) -> a -> a -> c:
import Data.Function(on)
addEven :: Integral a => [a] -> [a] -> [a]
addEven = addList `on` filter even
While using filter is very instinctive in this case, perhaps using filter twice and then summing up the results might be slightly ineffficient for large lists. Why don't we do the job all at once for a change..?
addMatches :: [Int] -> [Int] -> [Int]
addMatches [] [] = []
addMatches [] ys = filter even ys
addMatches xs [] = filter even xs
addMatches xs ys = first [] xs ys
where
first :: [Int] -> [Int] -> [Int] -> [Int]
first rs [] ys = rs ++ filter even ys
first rs (x:xs) ys = rs ++ if even x then second [x] xs ys
else first [] xs ys
second :: [Int] -> [Int] -> [Int] -> [Int]
second [r] xs [] = [r] ++ filter even xs
second [r] xs (y:ys) = if even y then first [r+y] xs ys
else second [r] xs ys
λ> addMatches [1,2,1,4,6] [2,2]
[4,6,6]
I am practicing some Haskell exam paper questions, and have come across the following
Define a Haskell function weaveHunks which takes an int and
two lists and weaves them together in hunks of the given size.
Be sure to declare its type signature.
Example:
weaveHunks 3 "abcdefghijklmno" "ABCDEFGHIJKLMNO"
=> "abcABCdefDEFghiGHIjklJKLmnoMNO"
I have found the following on Stack Overflow, which is just too weave two lists together but only in chunks of 1
weaveHunks :: [a] -> [a] -> [a]
weaveHunks xs [] = xs
weaveHunks [] ys = ys
weaveHunks (x:xs) (y:ys) = x : y : weaveHunks xs ys
I am having problems adjusting this to take chunks fo n size, I am very new to Haskell but this is what I have so far
weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks n xs [] = xs
weaveHunks n [] ys = ys
weaveHunks n xs ys = (take n xs) : (take n ys) : weaveHunks n (drop n xs) (drop n ys)
I am getting an error on the last line
(Couldn't match type a' with[a]')
Is (drop n xs) not a list?
You're very close!
By using the : operator to prepend the hunks, you're expressing that take n xs is one element of the result list, take n ys the next, and so on. But actually in both cases it's multiple elements you're prepending. That's the [a] that should actually be just a.
The solution is to use the ++ operator instead, which prepends an entire list rather than just a single element.
This is the full solution as I'd write it:
weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks _ xs [] = xs
weaveHunks _ [] ys = ys
weaveHunks n xs ys = xHunk ++ yHunk ++ weaveHunks n xRemain yRemain
where [(xHunk, xRemain), (yHunk, yRemain)] = splitAt n <$> [xs,ys]
As #leftaroundabout said, since your appending lists of type [a], you need to use ++ instead of :. With this in mind, your code would then look like this:
weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks _ xs [] = xs
weaveHunks _ [] ys = ys
weaveHunks n xs ys = (take n xs) ++ (take n ys) ++ weaveHunks n (drop n xs) (drop n ys)
If your interested, you can also use library functions to do this task:
import Data.List.Split
weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks n xs ys = concat $ zipWith (++) (chunksOf n xs) (chunksOf n ys)
Note: chunksOf is from Data.List.Split, which splits the list into sublists of length n, so the type of this function is Int -> [a] -> [[a]]. zipWith zips two lists based on a condition, in this case concatenation ++. concat turns a list of [[a]] into [a].
How can I write a takeWhile that would keep the first element that doesn't match the condition?
Example (obviously my example is trickier than this) :
Instead of takeWhile (\× - > x! = 3) [1..10] to return [1,2] I need [1,2,3].
I thought of (takeWhile myFunc myList) ++ [find myFunc myList] but it means I need to go through my list 2 times...
Any idea?
You can use span or break.
λ> span (/=3) [1..10]
([1,2],[3,4,5,6,7,8,9,10])
So you can do something like this:
takeWhileInc :: (a -> Bool) -> [a] -> [a]
takeWhileInc p xs = case zs of [] -> error "not found"
(z:_) -> ys ++ [z]
where
(ys, zs) = span p xs
(Or whatever you want to happen when zs is empty because no 3
was found.)
You can roll your own.
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p = foldr (\x ys -> if p x then x:ys else [x]) []
Compare it with
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p = foldr (\x ys -> if p x then x:ys else []) []
Explicit recursion would also be fine for this.
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p [] = []
takeWhileOneMore p (x:xs) =
if p x
then x : takeWhileOneMore p xs
else [x]
I like to use the base function more than many people do, such as re-using takeWhile in an intelligent way to get the desired result. For example, you can create a new list of predicates with the first element being True and takeWhile this list is true:
takeWhileP1 p xs = map snd (takeWhile fst (zip (True:map p xs) xs)
This generalizes nicely as well (not necessarily efficient in this form):
takeWhilePlusN n p xs = map snd (takeWhile fst (zip (replicate n True ++ map p xs) xs))
Or perhaps easier to read:
takeWhilePlusN n p xs =
let preds = replicate n True ++ map p xs
annotated = zip preds xs
in map snd (takeWhile fst annotated)
And the result:
*Main> takeWhilePlusN 3 (<5) [1..10]
[1,2,3,4,5,6,7]
*Main> takeWhilePlusN 1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhileP1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhile (<5) [1..10]
[1,2,3,4]
When the condition fails for a element, instead of terminating with empty list, we can return the element.
takeWhileInclusive :: (a->Bool) -> [a] -> [a]
takeWhileInclusive _ [] = []
takeWhileInclusive predicate (x:xs) = if predicate x
then do (x: takeWhileInclusive predicate xs)
else [x]
So i have
pair:: [a] -> [b] -> [(a,b)]
pair[] _ = []
pair(x:xs) (y:ys) = (x, y) : prod xs ys
But the result are only like the following:
>> pair [1,2] [3,4]
>> [(1,3),(2,4)]
How can I make this so it pairs like:
[(1,3),(1,4),(2,3),(2,4)]
You can use the list applicative (or monad) instance:
λ> liftA2 (,) [1,2] [3,4]
[(1,3),(1,4),(2,3),(2,4)]
Or, equivalently,
f = do
x <- [1,2]
y <- [3,4]
return (x,y)
You can also use a list comprehension:
[ (x,y) | x <- [1,3], y <- [2,4] ]
Although there is already a much more elegant answer, i think it is worthwhile to show how this would be achieved in a simple straightforward way. If you want to get all pairs, you obviously need to visit every element of one list for an element in the other.
pair :: [a] -> [b] -> [(a, b)]
pair [] _ = []
pair (x:xs) ys = pair' x ys ++ pair xs ys where
pair' :: a -> [b] -> [(a, b)]
pair' _ [] = []
pair' x (y:ys) = (x,y) : pair' x ys
But of course using the pair = liftA2 (,) or [1,3] >>= \x -> [2,4] >>= \y -> (x,y) in its do notation or list comprehension notation is much better. Also ++ isn't what you normally want to do. So maybe you can build the lists as pair' would do, keep them in a list and then concat them.
concat $ map (\x -> map (\y -> (x,y)) ys) xs
I want to filter a list by predicates curried from another list.
For instance:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter _ _ [] = []
multifilter _ [] _ = []
multifilter f (x:xs) ys = (filter (f x) ys) ++ (multifilter f xs ys)
With usage such as:
prelude> multifilter (==) [1,2,3] [5,3,2]
[2,3]
Is there a standard way to do this?
You can use intersectBy:
λ> :t intersectBy
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
λ> intersectBy (==) [1,2,3] [5,3,2]
[2,3]
You can use hoogle to search functions using type signature and finding them.
Note: This answer implements the specification expressed by the words and example in the question, rather than the different one given by the implementation of multifilter there. For the latter possibility, see gallais' answer.
Sibi's answer shows how you should actually do it. In any case, it is instructive to consider how you might write your function using filter. To begin with, we can establish two facts about it:
multifilter can be expressed directly as filter pred for some appropriate choice of pred. Given a fixed "predicate list", whether an element of the list you are multifiltering will be in the result only depends on the value of that element.
In multifilter f xs ys, the list you are filtering is xs, and the "predicate list" is ys. Were it not so, you would get [3,2] rather than [2,3] in your (quite well-chosen) example.
So we have:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred = undefined -- TODO
All we need to do is implementing pred. Given an element x, pred should produce True if, for some element y of ys, f x y is true. We can conveniently express that using any:
pred x = any (\y -> f x y) ys
-- Or, with less line noise:
pred x = any (f x) ys
Therefore, multifilter becomes...
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred x = any (f x) ys
-- Or, more compactly:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter (\x -> any (f x) ys) xs
... which is essentially equivalent to intersectBy, as you can see by looking at intersectBy's implementation.
A third option is to use a list comprehension:
multifilter rel xs ys = [ x | x <- xs, y <- ys, x `rel` y ]
or, if you want partial application:
multifilter p xs ys = [ x | x <- xs, let f = p x, y <- ys, f y ]
If you want to use filter,
relate rel xs ys = filter (uncurry rel) $ liftM2 (,) xs ys
(and throw in map fst)
The answer you have accepted provides a function distinct from the one defined in your post: it retains elements from xs when yours retains elements from ys. You can spot this mistake by using a more general type for multifilter:
multifilter :: (a -> b -> Bool) -> [a] -> [b] -> [b]
Now, this can be implemented following the specification described in your post like so:
multifilter p xs ys = fmap snd
$ filter (uncurry p)
$ concatMap (\ x -> fmap (x,) ys) xs
If you don't mind retaining the values in the order they are in in ys then you can have an even simpler definition:
multifilter' :: (a -> b -> Bool) -> [a] -> [b] -> [b]
multifilter' p xs = filter (flip any xs . flip p)
Simply use Hoogle to find it out via the signature (a -> a -> Bool) -> [a] -> [a] -> [a]
https://www.haskell.org/hoogle/?hoogle=%28a+-%3E+a+-%3E+Bool%29+-%3E+%5Ba%5D+-%3E+%5Ba%5D+-%3E+%5Ba%5D
yields intersectBy:
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]