EDIT FOR CLARITY: I know what the 'head of empty list' error is and why it is thrown. What I don't know is why there is no error when I use 'elem' but there is if I use 'mElem'. That's the only change I make to cause the error.
If I use the 'Prelude.elem' function the program runs but with one small error. I wrote my version of 'elem' (mElem) to counter this error. I looked at the source code for 'elem' and wrote my function in a similar style. However, the program crashes due to a 'head of empty list error' resulting from the function 'getExisting'
genTupleCount :: [F.Record] -> [(String, Int)] -> [(String, Int)]
genTupleCount [] tuples = tuples
genTupleCount (x:xs) tuples | mElem (F.club x) (map fst tuples) = genTupleCount xs $ getNewTuples tuples existing
| otherwise = genTupleCount xs $ (F.club x, 1):tuples
where
existing = getExisting x tuples
getExisting :: F.Record -> [(String, Int)] -> (String, Int)
getExisting x tuples = head $ filter ((==F.club x).fst) tuples
getNewTuples :: [(String, Int)] -> (String, Int) -> [(String, Int)]
getNewTuples old e = (fst e, 1 + (snd e)):(delete e old)
mElem :: String -> [String] -> Bool
mElem _ [] = False
mElem str (x:xs) = (map toLower str) == (map toLower x) || mElem str xs
As Matt Fenwick said, you're assuming there is an element that satisfies your condition. I suggest using find instead:
getExisting :: F.Record -> [(String, Int)] -> Maybe (String, Int)
getExisting x = find ((==F.club x).fst)
This handles the case of there not being any such element by returning Nothing, and let's you skip mElem entirely; just check the result of getExisting to find out whether there is any such element, and if there is, what its value is.
As to why using mElem instead of elem causes your program to crash, it is because it does not verify that there is an element that satisfies the condition getExisting searches for. getExisting doesn't normalise the capitalisation as mElem does, so if nElem returns True only because of its case-folding, then the call to getExisting will occur, and it will perform head on the empty list, because filter will find no elements matching getExisting's stricter condition.
The find solution avoids this potential for error, since it only has the condition in one place.
Your function getExisting assumes that the result of filter ((==F.club x).fst) tuples has at least one element.
Example:
Prelude> head [3,4]
3
Prelude> head []
*** Exception: Prelude.head: empty list
It looks like switching to mElem causes an empty list to eventually be passed to head. Apparently, this doesn't happen using elem.
Related
if list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25],
and list2 = [14,14,24,24,1,1,2,2]
How could I return a int list which is [0,0,1,1,2,2,3,3]
I have used the function
elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x
and the result for this for the first one
0
to get the index from list 1 for a single digit
But what I want is
findIndex :: [Int] -> [Int] -> [Int]
That would input two int list and return the index value base on the key list
How could I recursively get the index for one list or using any import function, such as map.
You've done a very good job of breaking the problem down. You've already recognized that you're doing the same thing for each element of the second list, and you've written a function to capture that behavior.
elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x
Now you want to take this function and apply it to each element of another list, collecting the results into a new list. That is, you want something that looks like
mystery :: (a -> b) -> [a] -> [b]
And we can search Hoogle and find exactly that function: map
map :: (a -> b) -> [a] -> [b]
map takes a function and a list and applies it to each element. You've got a function (elemIndex', with appropriate partial application), and you've got a list (list2 in your example). So let's put it together.
findAll :: Eq a => [a] -> [a] -> [Int]
findAll haystack needles = map (\x -> elemIndex' x haystack) needles
There are lots of streaming functions in Haskell like map, and knowing / figuring out which one to use in a given situation comes with practice. If you're ever in doubt, remember that you can use Hoogle to search for a type or you can simply do whatever you're trying to do recursively (if you didn't know map existed, you could write it yourself with a bit of recursion), and you'll get the hang of it over time. Good luck in your Haskell endeavors!
As an alternative to the answer by #SilvioMayolo, you could use a Map data structure. We zip in the indexes for each value in list1 and then turn that into a map, then just do a lookup for each value in list2.
import Data.Map
import Data.List
list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25]
list2 = [14,14,24,24,1,1,2,2]
map1 = Data.Map.fromList $ list1 `zip` [0..]
-- fromList [(0,11),(1,2),(2,3),(3,20),(4,14),(5,23),(6,24),
-- (7,5),(8,7),(9,15),(10,16),(11,4),(12,8),(13,21),
-- (14,0),(15,12),(16,22),(17,19),(18,18),(19,13),
-- (20,10),(21,17),(22,9),(23,6),(24,1),(25,25)]
list3 = Data.List.map (map1 !) list2
-- [0,0,1,1,2,2,3,3]
I'm writing a function that gets the index of the first even number from a list. The list I get may or may not contain even numbers, and I'd like to return -1 if there are no even numbers in the list. The list can be infinite.
I wrote this
posicPrimerPar'' :: [Int] -> Int
posicPrimerPar'' a = fromJust (elemIndex (head (filter (even) a)) a)
I could do something like:
posicPrimerPar' :: [Int] -> Int
posicPrimerPar' a = case length evens of
0 -> -1;
n -> fromJust elemIndex (head evens) a
where evens = filter (even) a
But as you can see, this is not the most efficient way of doing it. A list [1..100000] contains a lot of even numbers, and I just need the first one. I need Haskell's laziness, so I need to ask for the head right there, but head throws an empty list exception when the list is empty (i.e. there are no even numbers in the list). I cannot find the Haskell equivalent of Python's try: ... except: .... All I could find regarding exceptions were IO related. What I need is except Prelude.head = -1 or something like that.
Haskell is lazy, so evens will not be fully evaluated. The problematic part is the length evens which is not necessary. You can check with null :: Foldable f => f a -> Bool, or with pattern matching. For example:
import Data.List(findIndex)
posicPrimerPar' :: [Int] -> Maybe Int
posicPrimerPar' [] = Nothing
posicPrimerPar' xs = findIndex even xs
for findIndex :: (a -> Bool) -> [a] -> Maybe Int, you however do not need to take into account the empty list, since it already considers this.
or we can return -1 in case there is no such item:
import Data.List(findIndex)
import Data.Maybe(fromMaybe)
posicPrimerPar' :: [Int] -> Int
posicPrimerPar' = fromMaybe (-1) . findIndex even
I want to write a function pack such that
pack ['a','a','a','b','c','c','a','a','d','e','e','e']
= ["aaa","b","cc","aa","d","eee"]
How can I do this? I'm stuck...
Use Data.List.group:
λ> import Data.List (group)
λ> :t group
group :: Eq a => [a] -> [[a]]
λ> group ['a','a','a','b','c','c','a','a','d','e','e','e']
["aaa","b","cc","aa","d","eee"]
Unless you want to write the function yourself (see Michael Foukarakis answer)
Here's something off the top of my head:
pack :: (Eq a) => [a] -> [[a]]
pack [] = []
-- We split elements of a list recursively into those which are equal to the first one,
-- and those that are not. Then do the same for the latter:
pack (x:xs) = let (first, rest) = span (==x) xs
in (x:first) : pack rest
Data.List already has what you're looking for, though.
I think it's worth adding a more explicit/beginner version:
pack :: [Char] -> [String]
pack [] = []
pack (c:cs) =
let (v, s) = findConsecutive [c] cs
in v : pack s
where
findConsecutive ds [] = (ds, [])
findConsecutive s#(d:ds) t#(e:es)
| d /= e = (s, t)
| otherwise = findConsecutive (e:s) es
If the input is an empty list, the outcome is also an empty list. Otherwise, we find the next consecutive Chars that are equal and group them together into a String, which is returned in the result list. In order to do that we use the findConsecutive auxiliary function. This function's behavior resembles the takeWhile function, with the difference that we know in advance the predicate to use (equality comparison) and that we return both the consumed and the remaining list.
In other words, the signature of findConsecutive could be written as:
findConsecutive :: String -> [Char] -> (String, String)
which means that it takes a string containing only repeated characters to be used as an accumulator and a list whose characters are "extracted" from. It returns a tuple containing the current sequence of elements and the remaining list. Its body should be intuitive to follow: while the characters list is not empty and the current element is equal to the ones in the accumulator, we add the character to the accumulator and recursive into the function. The function returns when we reach the end of the list or a different character is encountered.
The same rationale can be used to understand the body of pack.
The language I'm using is a subset of Haskell called Core Haskell which does not allow the use of the built-in functions of Haskell. For example, if I were to create a function which counts the number of times that the item x appears in the list xs, then I would write:
count = \x ->
\xs -> if null xs
then 0
else if x == head xs
then 1 + count x(tail xs)
else count x(tail xs)
I'm trying to create a function which outputs a list xs with its duplicate values removed. E.g. remdups (7:7:7:4:5:7:4:4:[]) => (7:4:5:[])
can anyone offer any advice?
Thanks!
I'm guessing that you're a student, and this is a homework problem, so I'll give you part of the answer and let you finish it. In order to write remdups, it would be useful to have a function that tells us if a list contains an element. We can do that using recursion. When using recursion, start by asking yourself what the "base case", or simplest possible case is. Well, when the list is empty, then obviously the answer is False (no matter what the character is). So now, what if the list isn't empty? We can check if the first character in the list is a match. If it is, then we know that the answer is True. Otherwise, we need to check the rest of the list -- which we do by calling the function again.
elem _ [] = False
elem x (y:ys) = if x==y
then True
else elem x ys
The underscore (_) simply means "I'm not going to use this variable, so I won't even bother to give it a name." That can be written more succinctly as:
elem _ [] = False
elem x (y:ys) = x==y || elem x ys
Writing remdups is a little tricky, but I suspect your teacher gave you some hints. One way to approach it is to imagine we're partway through processing the list. We have part of the list that hasn't been processed yet, and part of the list that has been processed (and doesn't contain any duplicates). Suppose we had a function called remdupHelper, which takes those two arguments, called remaining and finished. It would look at the first character in remaining, and return a different result depending on whether or not that character is in finished. (That result could call remdupHelper recursively). Can you write remdupHelper?
remdupHelper = ???
Once you have remdupHelper, you're ready to write remdups. It just invokes remdupHelper in the initial condition, where none of the list has been processed yet:
remdups l = remdupHelper l [] -- '
This works with Ints:
removeDuplicates :: [Int] -> [Int]
removeDuplicates = foldr insertIfNotMember []
where
insertIfNotMember item list = if (notMember item list)
then item : list
else list
notMember :: Int -> [Int] -> Bool
notMember item [] = True
notMember item (x:xs)
| item == x = False
| otherwise = notMember item xs
How it works should be obvious. The only "tricky" part is that the type of foldr is:
(a -> b -> b) -> b -> [a] -> b
but in this case b unifies with [a], so it becomes:
(a -> [a] -> [a]) -> [a] -> [a] -> [a]
and therefore, you can pass the function insertIfNotMember, which is of type:
Int -> [Int] -> [Int] -- a unifies with Int
isTogether' :: String -> Bool
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
For the above code, I want to go through every character in the string. I am not allowed to use recursion.
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
If I've got it right, you are interested in getting consequential char pairs from some string. So, for example, for abcd you need to test (a,b), (b,c), (c,d) with some (Char,Char) -> Bool or Char -> Char -> Bool function.
Zip could be helpful here:
> let x = "abcd"
> let pairs = zip x (tail x)
it :: [(Char, Char)]
And for some f :: Char -> Char -> Bool function we can get uncurry f :: (Char, Char) -> Bool.
And then it's easy to get [Bool] value of results with map (uncurry f) pairs :: [Bool].
In Haskell, a String is just a list of characters ([Char]). Thus, all of the normal higher-order list functions like map work on strings. So you can use whichever higher-order function is most applicable to your problem.
Note that these functions themselves are defined recursively; in fact, there is no way to go through the entire list in Haskell without either recursing explicitly or using a function that directly or indirectly recurses.
To do this without recursion, you will need to use a higher order function or a list comprehension. I don't understand what you're trying to accomplish so I can only give generic advice. You probably will want one of these:
map :: (a -> b) -> [a] -> [b]
Map converts a list of one type into another. Using map lets you perform the same action on every element of the list, given a function that operates on the kinds of things you have in the list.
filter :: (a -> Bool) -> [a] -> [a]
Filter takes a list and a predicate, and gives you a new list with only the elements that satisfy the predicate. Just with these two tools, you can do some pretty interesting things:
import Data.Char
map toUpper (filter isLower "A quick test") -- => "QUICKTEST"
Then you have folds of various sorts. A fold is really a generic higher order function for doing recursion on some type, so using it takes a bit of getting used to, but you can accomplish pretty much any recursive function on a list with a fold instead. The basic type of foldr looks like this:
foldr :: (a -> b -> b) -> b -> [a] -> b
It takes three arguments: an inductive step, a base case and a value you want to fold. Or, in less mathematical terms, you could think of it as taking an initial state, a function to take the next item and the previous state to produce the next state, and the list of values. It then returns the final state it arrived at. You can do some pretty surprising things with fold, but let's say you want to detect if a list has a run of two or more of the same item. This would be hard to express with map and filter (impossible?), but it's easy with recursion:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:y:xs) | x == y = True
hasTwins (x:y:xs) | otherwise = hasTwins (y:xs)
hasTwins _ = False
Well, you can express this with a fold like so:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:xs) = snd $ foldr step (x, False) xs
where
step x (prev, seenTwins) = (x, prev == x || seenTwins)
So my "state" in this fold is the previous value and whether we've already seen a pair of identical values. The function has no explicit recursion, but my step function passes the current x value along to the next invocation through the state as the previous value. But you don't have to be happy with the last state you have; this function takes the second value out of the state and returns that as the overall return value—which is the boolean whether or not we've seen two identical values next to each other.