Классическая ошибка заключается в реализации слишком большого количества логики в одной функции.Вместо того, чтобы пытаться выполнить полное декодирование в функцию numbers
, может быть, лучше разделить задачи на компоненты многократного использования, чтобы их было легко понять, отладить и использовать повторно.
Здесь как первыйфункция, мы можем сопоставить цифру с String
, содержащим символы, например:
digtoseq :: Char -> String
digtoseq '2' = "abc"
digtoseq '3' = "def"
digtoseq '4' = "ghi"
digtoseq '5' = "jkl"
digtoseq '6' = "mno"
digtoseq '7' = "pqrs"
digtoseq '8' = "tuv"
digtoseq '9' = "wxyz"
digtoseq '0' = " "
Мы можем добавить дополнительные символы, например '.'
, чтобы указать последовательность после каждой телефонной клавиши.
Теперь мы можем реализовать функцию, которая использует digtoseq
, например digstrtoseq
:
digstrtoseq :: String -> Char
digstrtoseq (x:xs) = digtoseq x !! length xs
здесь мы, таким образом, берем длину строки, а также первый символи мы перемещаемся по строке digtoseq x
, чтобы получить n-1
-й элемент (с n
длиной входной строки).Таким образом, для "22"
мы получаем:
Prelude> digstrtoseq "22"
'b'
Prelude> digstrtoseq "33"
'e'
Prelude> digstrtoseq "2"
'a'
, так что теперь map
проверяет эту функцию на строке ввода:
numbers :: [String] -> String
numbers = map digstrtoseq
и затем мыполучить:
Prelude> numbers ["22", "33", "2"]
"bea"
Обратите внимание, что здесь мы сделали некоторые предположения, некоторые из которых можно улучшить, переписав функции, другие лучше решить, изменив тип ввода:
- мы предполагаем, что ни одна строка не имеет длину больше, чем длина последовательности за ней, поэтому
"2222"
не произойдет; - мы предполагаем, что символ в строковом элементе повторяется по всей строке, поэтому
"231"
не произойдет; - мы предполагаем, что строки содержат только допустимые цифры, поэтому нет
"~"
; - мы предполагаем, что каждая строка содержит хотя бы один символ, поэтому
""
.
Большая часть предположений проистекает из того факта, что мы здесь используем [String]
в качестве типа ввода, что дает большую свободу.Да, возможно выдавать ошибки или возвращать Nothing
в этом случае, но может быть лучше определить тип, например:
data Key = Two | Three | Four | Five | Six | Seven | Eight | Nine | Zero
, а затем в качестве ввода взять [(Key, Int)]
, с тех пор предположения(2) и (3) просто «гарантированы» через тип ввода.