elemIndex in conjunction with splitAt Haskell - haskell

I'm pretty new to Haskell and can't figure out how to solve the following problem that I have.
I have to implement the following function "ca" which takes a list and an element and deletes all of the other elements in the list after the input element:
ca:: Eq a => a -> [a] -> [a]
I'm not allowed to change any of the function types and have so far come up with the following code:
ca x xs = let (ys, zs) = splitAt (elemIndex x xs) xs in ys
This produces the following error:
couldn't match expected type 'Int' with the actual type 'Maybe Int'
Now I understand why this error is occurring however I do not understand how I can fix it. Any help would be appreciated.

Instead of using indexes, you can use the break function, which splits a list just before the position where a predicate first becomes True.
> break (== 'x') "aabaaccxaabbcc"
("aabaacc","xaabbcc")
Or, since you're discarding the second part anyway, you can use takeWhile.
> takeWhile (/= 'x') "aabaaccxaabbcc"
"aabaacc"

This should typecheck, although the function is unsafe now:
import Data.List
import Data.Maybe (fromJust)
ca x xs = let (ys, zs) = splitAt (fromJust $ elemIndex x xs) xs in ys
The reason is elemIndex type is elemIndex :: Eq a => a -> [a] -> Maybe Int and you want to extract the Int out of the Maybe and pass it to the splitAt function. This is what fromJust function does. fromJust will extract out the value from Just datatype.
You can try writing the safe alternative of this function using maybe or any other alternative function.

You can do this:
let
Just n = elemIndex x xs
(ys, zs) = splitAt n xs
in ys
However, if the specified element isn't present, this will throw an exception due to a "pattern match failure". A better way is this:
case elemIndex x xs of
Just n -> let (ys, zs) = splitAt n xs in ys
Nothing -> {- decide what to do if there's no match! -}
However, I concur with Hammar. You're not really trying to split the list into two parts; you're only interested in one of those parts. So rather than hunt through the list, find the element you want, return its index, and then hunt through the list a second time, why not just use break or takeWhile?

Related

Haskell - Filtering a list of tuples

Consider this list of tuples:
[(57,48),(58,49),(59,50),(65,56),(65,47),(65,57),(65,49), (41, 11)]
I want to remove a tuple (a, b) if its second element b is equal to the first element of another tuple and all the tuples with the same a that come after it. For example:
The second element of (65,57) is 57 and the first tuple in the list (57,48)has 57 as its first element, so (65,57) should be removed and all tuples that come after it that start with 65, namely (65,49). The tuples that come before it, (65,56) and (65,47), should stay in the list.
Does anyone have an idea how to do this?
For efficiency (single pass), you should create two sets, one for elements you've seen as the first elements of tuples, the other for elements you've seen both as first and second elements (ie. delete if matches first element).
Something like,
{-# LANGUAGE PackageImports #-}
import "lens" Control.Lens (contains, (.~), (^.), (&))
import "yjtools" Data.Function.Tools (applyUnless, applyWhen)
import qualified "containers" Data.IntSet as Set
filterTuples :: Foldable t => t (Int, Int) -> [(Int, Int)]
filterTuples = flip (foldr go $ const []) (Set.empty, Set.empty)
where
go p#(x,y) go' (fsts, deletes) =
let seenFst = fsts ^. contains y
shouldDelete = seenFst || deletes ^. contains x
fsts' = fsts & contains x .~ True
deletes' = deletes & applyWhen seenFst (contains y .~ True)
in applyUnless shouldDelete (p:) $ go' (fsts', deletes')
EDITs: for correctness, clarity, spine-laziness
You could start by creating a distinct set of all the first elements, e.g.:
Prelude Data.List> firsts = nub $ fst <$>
[(57,48),(58,49),(59,50),(65,56),(65,47),
(65,57),(65,49), (41, 11)]
Prelude Data.List> firsts
[57,58,59,65,41]
You could use break or span as Robin Zigmond suggests. You'll need a predicate for that. You could use elem, like this:
Prelude Data.List> elem 48 firsts
False
Prelude Data.List> elem 49 firsts
False
...
Prelude Data.List> elem 57 firsts
True
If you're concerned that elem is too inefficient, you could experiment with creating a Set and use the member function instead.
Perhaps try using mapAccumL starting with the initial list as the accumulator. Then maintain a Predicate as a parameter too which acts as a decider for what has been seen, and this will determine if you can output or not at each step in the traversal.
I'm an absolute beginner in haskell, so there probably is a much more elegant/efficient solution for this. But anyways I wanted to share the solution I came up with:
filterTuples :: [(Int, Int)] -> [(Int,Int)]
filterTuples [] = []
filterTuples (x:xs) = x:filterTuples(concat ((fst temp) : [filter (\z -> fst z /= del) (snd temp)]))
where del = fst (head (snd temp))
temp = break (\y -> (snd y == fst x)) xs
(Glad for feedback on how to improve this)
f consumes a list of pairs: xs; it produces a new list of pairs: ys. ys contains every pair: (a, b) in xs, except the pair whose second element b: previously occurred as first elements: a. When such a pair: (a, b) is encountered, subsequent pairs that have a as their first elements are excluded from ys.
f xs = go xs [] []
where
go [] ys zs = ys
go (x#(a,b):xs) ys zs
| b `elem` as = go xs ys (a:zs)
| a `elem` zs = go xs ys zs
| otherwise = [x] ++ go xs ys zs
as = (nub . fst . unzip) xs

Recursion with Maybe

I'm having difficulty try to write a function to find the sum of two lists using recursion, that possibly could be Nothing if any list is empty.
The math of the following functions are:
Σw[i]x[i]
where w and x are equal length int arrays
Here is my working code:
example :: [Int] -> [Int] -> Int
example [] [] = 0
example (x:xs) (l:ls) = ((x*l) + (example xs ls))
Here is the idea of what I want to work:
example :: [Int] -> [Int] -> Maybe Int
example [] [] = Nothing
example (x:xs) (l:ls) = Just((x*l) + (example xs ls))
Thanks
I'm guessing at what your intent is here, not sure whether I read it correctly: You want the function to produce Nothing when the two input lists have difference lengths?
The "happy" base case is 0 just like in the first attempt, but lifted into Maybe.
example [] [] = Just 0
To handle situations where the lists have different lengths, include the cases where only one of the lists is empty. You should have gotten a compiler warning about a non-exhaustive pattern match for not including these cases.
example [] _ = Nothing
example _ [] = Nothing
The final case, then, is where you have two nonempty lists. It looks a lot like that line from your first attempt, except rather than applying the addition directly to example xs ys, we fmap the addition over example xs ys, taking advantage of the fact that Maybe is a Functor.
example (x : xs) (y : ys) = fmap (x * y +) (example xs ys)
Example usage:
λ> example [1,2] [3,4]
Just 11
λ> example [1,2] [3,4,5]
Nothing
By the way, if you wanted to use a library this, safe would be a nice choice to turn this into a one-liner.
import Safe.Exact
example xs ys = fmap sum (zipWithExactMay (*) xs ys)
You're close, but your recursive call to example xs ls returns a Maybe Int, and you can't add an Int and a Maybe Int (in x*l + example xs ls), hence your error on the last line.
You can use fromMaybe to deal with this case, using 0 as the default sum:
example :: [Int] -> [Int] -> Maybe Int
example [] [] = Nothing
example (x:xs) (l:ls) = Just $ x * l + fromMaybe 0 (example xs ls)
Alternatively (and more neatly), you can avoid the explicit recursion using something like this:
example [] [] = Nothing
example xl yl = Just $ sum $ zipWith (*) xl yl
Note that you have non-exhaustive patterns in your pattern match. Two lists of different lengths will cause a pattern-match exception.

Learning haskell: a recursive function for creating skip-bigrams

I'm working my way through the NLPWP Book, and I'm at the chapter that deals with recursive functions. A recursive function for computing bigrams looks like this:
bigram :: [a] -> [[a]]
bigram [] = []
bigram [_] = []
bigram xs = take 2 xs : bigram (tail xs)
And if I run it on the wordlist = ["colorless", "green", "ideas", "sleep", "furiously"] I get this:
bigram chomsky
[("colorless","green"),("green","ideas"),("ideas","sleep"),("sleep","furiously")]
The exercise says:
A skip-bigram is any pair of words in sentence order. Write a function skipBigrams that extracts skip-bigrams from a sentence as a list of binary tuples, using explicit recursion. Running your function on ["Colorless", "green", "ideas", "sleep", "furiously"] should give the following output:
Prelude> skipBigrams ["Colorless", "green", "ideas", "sleep", "furiously"]
[("Colorless","green"),("Colorless","ideas"),("Colorless","sleep"),("Colorless","furiously"),("green","ideas"),("green","sleep"),("green","furiously"),("ideas","sleep"),("ideas","furiously"),("sleep","furiously")]
Here is the definition I've tried:
skipBigram [] = []
skipBigram [_] = []
skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]
But I'm getting the following error:
Occurs check: cannot construct the infinite type: t ~ [(t, t)]
Relevant bindings include
xs :: [t] (bound at :3:15)
x :: t (bound at :3:13)
skipBigram :: [t] -> [(t, t)] (bound at :1:1)
In the expression: interactive:IHaskell384.skipBigram xs
In the expression: (x, interactive:IHaskell384.skipBigram xs)
Which, new to Haskell as I am, I don't understand in the slightest. What is an infinite type? A relevant binding?
How should I define skipBigram to resolve this compile-time error?
you get this because your result is a list-of-pairs, where the second-part of the first item in that list is some element and the second-part of the second item in your result list is, whatever you are trying to give back (you use recursion here so it will have the same type) - so you say:
my result is a list-of-tuples, but part of those tuples is the result-type itself
that is what the error tells you
here are some details:
look at your last line
skipBigram (x:xs) = [(x, (head xs)), (x, skipBigram xs)]
you have a list of tuples on the right side so it's type will be like (based on the first element of the result list):
skipBigram :: [a] -> [(a,a)]
but in the second-item you have (x, skipBigram xs) meaning it will have the type (a, [(a,a)]) (remember the type of skipBigram xs is the above part).
and so - comparing the second parts of the tuples - you have a ~ [(a,a)] which produces your error because somehow the type a should be the same as [(a,a)] which you could expand in all eternity ;)
now to the algorithm itself:
It will not work like this - you somehow have to get all combinations and to do this you have to work with the items in the list.
Usually you either do this with list-comprehensions or with the do-notation of the list-monad.
To get going think about this:
f [] = [[]]
f (x:xs) =
let xss = f xs
in [ x:xs | xs <- xss ] ++ xss
test it and play with it in ghci - you will have to combine this with what you got somehow
(ok recursion.ninja ^^ spoiled your fun - I'll let this here anyway if you don't mind)
Try this definition:
skipBigram :: [a] -> [(a,a)]
skipBigram [] = [] -- nothing to do with an empty list
skipBigram (x:xs) = [(x,y) | y <- xs] ++ skipBigram xs
Your skipBigram function is generating all the "2-tuple left-to-right combinations" of words in the list. We can capture this concept with a simple list comprehension in the recursive definition. By recursively concatenating the simple list comprehensions, we gain the desired result list.
The infinite type error is complaining about your use of lists. Your function should have the type [a] -> [a] -> [(a, a)], but when GHC tries to infer your function's type, it gets that a = [a], an infinite type. Relevant bindings are just the types of other variables which may be causing the error.
However, even ignoring the type errors, your function will not do what you want at all. Firstly, your function will always return a list of length two, because you have explicitly constructed the list. Also, the result would include ("Colorless", "Colorless"), because (x, head xs) is the same here as (x, x).
Instead, try this solution
skipBigram :: [a] -> [(a, a)]
skipBigram [] = []
skipBigram (x:xs) = map (x,) xs ++ skipBigram xs
For this function to work, you will need to put the line
{-# LANGUAGE TupleSections #-}
at the beginning of your file.

How to return last element in the list using function in haskell?

My professor gave me an example to get last element in the list using "laste" function:
he stated that: definition in the form of “laste xs = …” is not acceptable, whereas definition in the form of “laste = …” is acceptable.
I have tried something like this: Please correct me if my solution is wrong according to problem statement.
laste :: [a] -> Maybe a
laste [] = Nothing
laste (x:[]) = Just x
laste (x:xs) = laste xs
But this gives me answer for example:
ghci>laste[1,2,3,4]
Just 4
I want to get rid of this "Just".
Is there any solution to remove Just?
You would need to change the signature of the function to return a simple element.
The thing is that you would need to return an error in case of empty list.
laste :: [a] -> a
laste [] = error "Can't handle empty lists." -- or some other error message
laste [x] = x
laste (x:xs) = laste xs
While Charmini2's answer is functionally correct, it doesn't solve the problem of retrieving the last element in pointfree form. Consider
laste :: [a] -> a
laste = foldr1 (\_ a -> a)
It works according to specs as foldr1 expects a non-empty list. Intuition for why it returns the last element in the list can be gotten from the observation that foldr1 replaces every (:) in the structure of the list with the lambda in the above equation, which basically selects the rightmost of two elements. Repeat, and you get the last.
I think your professor meant was that you need to re-implement the Prelude function last
in a point-free style.
non point-free example:
filterEven xs = filter even xs
point-free exapmle:
filterEven = filter even
point-free examples of last:
lastv1 = (head . reverse)
lastv2 = foldl1 (\acc x -> x)
lastv3 = foldr1 (\x acc -> acc)
lastv4 = \(x:xs) -> if null xs then x else lastv4 xs
lastv5 = \e -> case e of
[x] -> x
(_:xs) -> lastv5 xs
otherwise -> error "empty list"
Here a possible working solution:
last' :: [a] -> a
last' [] = error "empty"
last' (x:[]) = x
last' (x:xs) = last' xs

Haskell: Double every 2nd element in list

I just started using Haskell and wanted to write a function that, given a list, returns a list in which every 2nd element has been doubled.
So far I've come up with this:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Which works but I was wondering how you guys would write that function. Is there a more common/better way or does this look about right?
That's not bad, modulo the fixes suggested. Once you get more familiar with the base library you'll likely avoid explicit recursion in favor of some higher level functions, for example, you could create a list of functions where every other one is *2 and apply (zip) that list of functions to your list of numbers:
double = zipWith ($) (cycle [id,(*2)])
You can avoid "empty list" exceptions with some smart pattern matching.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
this is simply syntax sugar for the following
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
the pattern matching is done in order, so xs will be matched against the pattern x:y:xs first. Then if that fails, the catch-all pattern a will succeed.
A little bit of necromancy, but I think that this method worked out very well for me and want to share:
double2nd n = zipWith (*) n (cycle [1,2])
zipWith takes a function and then applies that function across matching items in two lists (first item to first item, second item to second item, etc). The function is multiplication, and the zipped list is an endless cycle of 1s and 2s. zipWith (and all the zip variants) stops at the end of the shorter list.
Try it on an odd-length list:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
And you can see the problem with your code. The 'head' and 'tail' are never a good idea.
For odd-lists or double_2nd [x] you can always add
double_2nd (x:xs) | length xs == 0 = [x]
| otherwise = x : (2 * head xs) : double_2nd (tail xs)
Thanks.
Here's a foldr-based solution.
bar :: Num a => [a] -> [a]
bar xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
(:)
((:) . (*2))
Testing:
> bar [1..9]
[1,4,3,8,5,12,7,16,9]

Resources