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
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
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.
find solution avoids this potential for error, since it only has the condition in one place.
getExisting assumes that the result of
filter ((==F.club x).fst) tuples has at least one element.
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