Haskell - Ошибка "Неисчерпывающие шаблоны" с функцией, использующей список

Я пытаюсь сделать функцию в haskell, чтобы знать, все ли элементы в списке списка имеют одинаковую длину. (Я ищу ответы в предыдущих постах, но ни один из них не работает).

sameLength :: [[t]] -> String
sameLength [] = "Empty list"
sameLength [[items]]
    | and $ map (\x -> length x == (length $ head [[items]])) [[items]] = "Same length"
    | otherwise = "Not the same length"

Проблема в том, что это не работает:

*Main> :l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> sameLength []
"Empty list"
*Main> sameLength [[1,2],[3,4]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength

*Main> sameLength [[1,2]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength

Я действительно не вижу, где проблема. Это относится к случаю, когда параметр является пустым списком и в котором его нет. Я ошибся? Я что-то пропустил?

Спасибо за вашу помощь:)

2 ответа

Решение

У тебя слишком много [..] здесь:

sameLength [[items]] 

(как Сильвио объяснил очень хорошо) - попробуйте

sameLength items 

вместо.

Дальше как a == aВам не нужно проверять, равна ли длина головы длине головы (конечно), и поэтому я бы порекомендовал сделать что-то вроде этого:

sameLength :: [[a]] -> Bool
sameLength []     = True
sameLength (h:tl) = all ((length h ==) . length) tl

как я думаю Bool результат просто полезнее и естественнее

как это работает?

all берет предикат и список и проверяет, выполняется ли предикат для каждого элемента списка - так (length h ==) . length = \xs -> length h == length xs в качестве предиката проверяет наличие заданного списка xs имеет ту же длину, что и головной список h - так что из-за замечания выше, вам нужно только проверить это с помощью хвостового списка tl

замечание

Вы можете поспорить, если все элементы пустого списка должны иметь одинаковую длину - но я думаю, что ответ должен быть да;)

Примеры

Prelude> sameLength [[1,2],[3,4]]
True
Prelude> sameLength [[1,2],[3,4,5]]
False
Prelude> sameLength [[1,2]]
True
Prelude> sameLength []
True

в случае, если вы беспокоитесь о производительности

(или вам не нравится стиль без очков)

sameLength :: [[a]] -> Bool
sameLength []     = True
sameLength (h:tl) = let l = length h
                    in all (\xs -> length xs == l) tl

Шаблон [x] соответствует списку, содержащему ровно один элемент, x, Таким образом, картина [[items]] соответствует одному списку, содержащему один элемент. То, что вы хотите, это сопоставить все непустые списки во втором случае. Но поскольку пустые списки уже сопоставлены, при удалении вы просто хотите сопоставить все, что еще не сопоставлено.

sameLength :: [[t]] -> String
sameLength [] = "Empty list"
sameLength items = -- Code here
Другие вопросы по тегам