Compare two lists with pattern matching in Haskell - list

I am trying to implement a function where I have two lists, the first is of any type and the second is a Boolean, and I want it to return just the first list if it is equal to true. For example:
pickIt [1, 2, 3] [True, False, True] returns [1, 3]
Here is my code:
pickIt :: [a] -> Bool -> [a]
pickIt (x:xs) (y:ys) = (x, y) : pickIt xs ys
pickIt _ _ = []
I think my type is wrong, but I am completely stumped on how to approach this. Any help, guidance, or a link to go in the right direction would be helpful.

Your type is wrong, you said you have a list of bools (in English) then your type said you have a single Bool. Use [Bool] instead of Bool.
You said (by example) that you want a list of the element from the first list, so [a], as a result. Then your code return tuples of (a,Bool) (i.e. see your (x,y) value). Instead test if y is true and only if so cons on x via x:.

Related

How do you write more than 1 line in an if statement in Haskell

I have an if-else statement, and in the else block I want it to first recurse to the function, except for the last two elements of the list, and then return two elements.
In the following function, after the if-else statement, I have 2 lines of code. however this doesnt compile. I believe the compiler reads these two lines as a single line of code. How do you fix that?
doubleEveryOther :: [Integer] -> [Integer] --outputs the input list, but every 2nd element(from the right) is doubled
doubleEveryOther [] = []
doubleEveryOther x = if (length x <2)
then
x
else
doubleEveryOther init (init x) -- These two lines
[2*last(init x), last x] -- These two lines
The compiler says:
* Couldn't match expected type: [Integer]
with actual type: [a0] -> [a0]
* Probable cause: `init' is applied to too few arguments
In the first argument of `doubleEveryOther', namely `init'
In the expression: doubleEveryOther init (init x)
In the expression:
[doubleEveryOther init (init x), 2 * last (init x), last x]
|
19 | [doubleEveryOther init (init x), 2*last(init x), last x]
|
You can not return two lists. If you have two results you want to combine, you use some function, like (++) :: [a] -> [a] -> [a].
That being said, you here don't need this. You can work with simple pattern matching:
doubleEveryOtherFromLeft :: Num a => [a] -> [a]
doubleEveryOtherFromLeft (x:y:xs) = 2*x : y : doubleEveryOtherFromLeft xs
doubleEveryOtherFromLeft xs = xs
then our doubleEveryOther can reverse the list twice:
doubleEveryOther:: Num a => [a] -> [a]
doubleEveryOther = reverse . doubleEveryOtherFromLeft . reverse
I think you are just missing the append operator ++:
doubleEveryOther (init (init x))
++ [2 * last (init x), last x]
I have an if-else statement, and in the else block I want it to first
recurse to the function, except for the last two elements of the list,
and then return two elements
OK. I sort of understand what you're doing. The function name is good - the best name is verb-noun, here doubleEveryOther. However, the code looks a lot like Lisp, probably Scheme - the repeated use of init gives it away. That's not how you write Haskell. (I also write Lisp in Haskell syntax too much...)
Haskell recursion works using pattern matching.
lst = [2,3,4]
1 : [2,3,4] -- [1,2,3,4]
lst = [1,2,3,4]
(x:xs) = lst -- x is 1, xs = [2,3,4]
So, in this case, you want to match your list against x:y:xs:
lst = [1,2,3,4]
(x:y:xs) = lst -- x is 1, y is 2, xs=[3,4]
Hence:
doubleEveryOther :: Num a => [a] -> [a]
doubleEveryOther [] = []
doubleEveryOther [x] = [2*x]
doubleEveryOther (x:y:xs) = (2*x):doubleEveryOther xs
Please note the number of special cases which need to be handled. If I am given an empty list, I should return an empty list. If I am given a single value, I need to double it (in analogy to your if .. else clause). If I am given two or more values, this matches x=first, y=second, xs=[] or more.
As for returning more than one value, you can return only one thing from a function. It can be a single value, a single tuple, a single list, and so on.
In this case, you have written a function which says doubleEveryOther - good - but then you want to return the last two values unchanged. You would be better taking off the last two values, running the simple doubleEveryOther and then bolting the last two values on the end. Otherwise, you are overburdening your function.

Comparison of two lists in Haskell

I have two lists in Haskell.
Original List: ["hello", "HELLO", "world", "WORLD"]
Only Upper Case List: ["HELLO", "WORLD"]
Could you help me to create a function which should return a list conatining the indexes of intersection of two lists.
I can get the first index by doing this:
let upperIndex = findIndices(==(onlyUpper !! 0)) original
However, this only works for one instance, in this case I can only get index of "HELLO" in the original list, but I want to get all of them.
For this example, the answer should be: [1,3]
Edit: Another version suggested by David Young is
findIndicesIn xs ys = findIndices (`elem` ys) xs
which I prefer to my solution below.
If I understand correctly, you have two lists. Call them xs and ys. You want to find the index in xs of each element in ys. You don't mention what you want to do if the element in ys is not contained in xs, so I am going to choose something reasonable for you. Here it is:
findIndicesIn :: Eq a => [a] -> [a] -> [Maybe Int]
findIndicesIn xs ys = map (`elemIndex` xs) ys
elemIndex :: Eq a => a -> [a] -> Maybe Int finds the index of the given element in the list (comparing with (==)). If the element does not exist, Nothing is returned instead. To find all the indices, we map over each element in ys and try to find it in xs using elemIndex. Section syntax is used instead of flip elemIndex xs or \y -> elemIndex y xs for concision.
The result is a list of Maybe Int representing the possible indices in xs of each element in ys. Note that if you do not keep track of missing elements, the positions of the indices in the resulting list will no longer correspond to the positions of the elements in ys.
You can also write this using fewer points as
findIndicesIn :: Eq a => [a] -> [a] -> [Maybe Int]
findIndicesIn xs = map (`elemIndex` xs)
YMMV on which one is more clear. Both are equivalent. This version is pretty readable IMO. You can go one step further and write
findIndicesIn = map . flip elemIndex
but personally I find this less readable. YMMV again.
let upperIndex original onlyUpper = helper original 0 where helper [] _ = []; helper (x:xs) i = if elem x onlyUpper then i:(helper xs (i+1)) else helper xs (i+1)
Example of use:
Prelude> upperIndex ["hello", "HELLO", "world", "WORLD"] ["HELLO", "WORLD"]
[1,3]

Inverting List Elements in Haskell

I am trying to invert two-elements lists in xs. For example, invert [[1,2], [5,6,7], [10,20]] will return [[2,1], [5,6,7], [20,10]]. It doesn't invert [5,6,7] because it is a 3 element list.
So I have written this so far:
invert :: [[a]] -> [[a]]
invert [[]] = [[]]
which is just the type declaration and an empty list case. I am new to Haskell so any suggestions on how to implement this problem would be helpful.
Here's one way to do this:
First we define a function to invert one list (if it has two elements; otherwise we return the list unchanged):
invertOne :: [a] -> [a]
invertOne [x, y] = [y, x]
invertOne xs = xs
Next we apply this function to all elements of an input list:
invert :: [[a]] -> [[a]]
invert xs = map invertOne xs
(Because that's exactly what map does: it applies a function to all elements of a list and collects the results in another list.)
Your inert function just operations on each element individually, so you can express it as a map:
invert xs = map go xs
where go = ...
Here go just inverts a single list according to your rules, i.e.:
go [1,2] = [2,1]
go [4,5,6] = [4,5,6]
go [] = []
The definition of go is pretty straight-forward:
go [a,b] = [b,a]
go xs = xs -- go of anything else is just itself
I would do this:
solution ([a,b]:xs) = [b,a] : solution xs
solution (x:xs) = x : solution xs
solution [] = []
This explicitly handles 2-element lists, leaving everything else alone.
Yes, you could do this with map and an auxiliary function, but for a beginner, understanding the recursion behind it all may be valuable.
Note that your 'empty list case' is not empty. length [[]] is 1.
Examine the following solution:
invert :: [[a]] -> [[a]]
invert = fmap conditionallyInvert
where
conditionallyInvert xs
| lengthOfTwo xs = reverse xs
| otherwise = xs
lengthOfTwo (_:_:_) = True
lengthOfTwo _ = False

Haskell - how to count elements in nested list

Lets say I have nested lsit: [1, [2, 3, 4], [5, [6]]] and I want to count how many elements it has. In this case it is six elements. I have written such code for doing this:
totalElems :: [a] -> Int
totalElems (x:xs) = case (x, xs) of
(_, []) -> 0
(y:ys, _) -> 1 + totalElems ys + totalElems xs
(_, _) -> 1 + totalElems xs
But I've got an error:
a.hs:4:42:
Couldn't match expected type ‘a’ with actual type ‘[a0]’
‘a’ is a rigid type variable bound by
the type signature for totalElems :: [a] -> Int at a.hs:1:15
Relevant bindings include
xs :: [a] (bound at a.hs:2:15)
x :: a (bound at a.hs:2:13)
totalElems :: [a] -> Int (bound at a.hs:2:1)
In the pattern: y : ys
In the pattern: (y : ys, _)
In a case alternative:
(y : ys, _) -> 1 + totalElems ys + totalElems xs
How I can do this in Haskell?
You can't make freeform lists-within-lists like that in Haskell. Dynamically typed langues will tolerate silliness like that, but strongly-typed Haskell won't.
1 is of type Int, and [2,3,4] is of a different type [Int]. Things in a list have to be of the same type.
However, you could do something like this:
data Nest a = Elem a | List [Nest a]
example ::Nest Int
example = List [Elem 1, List [Elem 2, Elem 3, Elem 4], List [Elem 5, List [Elem 6]]]
countNest :: Nest a -> Int
countNest (Elem x) = 1
countNest (List xs) = sum $ map countNest xs
Let's say I have nested lsit: [1, [2, 3, 4], [5, [6]]]
You can't have that list. It won't type-check. Try typing it by itself in GHCi; it'll just spit an error message at you. Since this input can't exist in the first place, trying to write a function to process it is a doomed endeavor.
Instead, you need to define a custom data type for this. See the other answers.
As others have said, the simplest way to do this is with a different data structure, like the tree NovaDenizen defined. However, just so you know, Haskell's type system enables various ways of creating "lists" in which the elements have different types : see https://wiki.haskell.org/Heterogenous_collections

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.