2012-01-03 6 views
0

EDIT FOR CLARITY: Я знаю, что такое ошибка «голова пустого списка» и почему она выбрасывается. Я не знаю, почему нет ошибки, когда я использую «elem», но есть, если я использую «mElem». Это единственное изменение, которое я делаю, чтобы вызвать ошибку.Как это небольшое изменение разбивает мою программу?

Если я использую функцию Prelude.elem, программа запускается с одной небольшой ошибкой. Я написал свою версию «elem» (mElem), чтобы встретить эту ошибку. Я посмотрел исходный код для «elem» и написал мою функцию в подобном стиле. Тем не менее, программа выходит из строя из-за «голову пустой список ошибок» в результате функции «» 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 
+0

Если я использую elem, ошибки не возникает, но если я изменю его на mElem, то ошибка, которую объяснил Мэтт. – Shane

+1

elem никогда не возвращался True, но mElem сделал, по-видимому, так что getExisting в конечном итоге получил оценку. – Ingo

ответ

3

Как сказал Мэтт Фенвик, вы предполагаете, что есть элемент, который удовлетворяет вашему состоянию. Я предлагаю использовать вместо find:

getExisting :: F.Record -> [(String, Int)] -> Maybe (String, Int) 
getExisting x = find ((==F.club x).fst) 

Это обрабатывает случай не является каким-либо таким элементом, возвращая Nothing, и давайте вы пропустите mElem полностью; просто проверьте результат getExisting, чтобы узнать, есть ли такой элемент, а если есть, каково его значение.

Как почему использование mElem вместо elem вызывает программу аварии, это происходит потому, что он делает не проверить, что есть элемент, который удовлетворяет условию getExisting поиски. getExisting не нормализуют капитализацию mElem делает, так что если, то будет происходить nElem возвращает значение ИСТИНА только из-за его прецедентном сворачивания вызов getExisting, и он будет выполнять head на пустой список, потому что filter не найдет элементы, соответствующие getExisting в более строгом состоянии.

Решение find устраняет этот потенциал ошибки, поскольку в нем есть условие только в одном месте.

+0

Как я сказал Мэтту, я знаю, что это моя ошибка. Я спросил, почему использование mElem вместо elem приводит к этой ошибке. – Shane

+1

@Aurora: Я обновил свой ответ. – ehird

+0

Я не обсуждаю, что другой код не должен приводить к другому результату, я просто задавался вопросом, почему это произошло в этом случае, поскольку я пытался смоделировать свой код на источнике elem. Эхирд ответил на вопрос – Shane

1

Ваша функция getExisting предполагает, что результат filter ((==F.club x).fst) tuples имеет, по меньшей мере, один элемент.

Пример:

Prelude> head [3,4] 
3 
Prelude> head [] 
*** Exception: Prelude.head: empty list 

Похоже, переключение на mElem вызывает пустой список в конечном счете, будет передан в head. По-видимому, этого не происходит, используя elem.

+0

Да, я знаю это, я сказал, что ошибка возникла по этой причине. Но как изменение в элементе «elem» вызывает эту ошибку? – Shane

+0

@Aurora - не могли бы вы уточнить, что такое «изменение» в «элеме»? Это не ясно в ОП. Я предполагаю, что использование 'mElem' приводит к тому, что пустой список будет передан в' head'. –

Смежные вопросы