2016-12-22 1 views
1

У меня возникли трудности с пониманием того, как использовать сопоставление образцов в стражах.Haskell - Pattern Соответствие форме (x: y: zs)

У меня есть эта функция выбора, целью которой является возвращение последнего символа в строку.

myFun :: [Char] -> Char 
myFun [email protected](f:s:rst) 
     | str == "" = error "0 length string" 
     | length str == 1 = head str 
     | rst == "" = s 
     | otherwise = lame (s:rst) 

Он не работает с «Неисчерпыванием шаблонов в функции» при передаче строки с одним символом.

Я предполагаю, что Haskell понимает, что он не может использовать форму (f:s:rst) для соответствия списку отдельных элементов, а затем сбой до попытки оценить вызов length.

Как сделать охрану, которая сообщит Haskell, что делать, когда есть только один элемент?

ответ

4

Вы являетесь образцом, соответствующим уровню определения функции. То, как вы описали, вы только покрывает случай, когда строка, по крайней мере два символа:

myFun [email protected](f:s:rst) 

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

myFun _ = ... 

Или, если вы хотите обработать, например, пустая строка, как это (до улов-все):

myFun [] = ... 

Как цели вашей функции, вы, вероятно, лучше всего с помощью сопоставления с образцом, а не с помощью охранников.

myFun :: [Char] -> Char 
myFun [] = error "empty string" 
myFun [x] = x 
myFun (x:xs) = myFun xs 

(Обратите внимание, что было бы более идиоматических вернуть Maybe Char вместо разбив программы)

+0

Это работает - Реалистично существует множество более простых/лучших способов сделать это. То, что я действительно борется с этим, пытается выяснить, есть ли способ рассказать охранникам, что делать, если аргумент не может быть деконструирован через предоставленный шаблон. Должен ли я принять ваш ответ, чтобы это означало: «Да, если вы определяете шаблон в объявлении функции, это невозможно при использовании защитных устройств» –

+2

Сначала происходит сопоставление шаблонов на уровне функций, что означает, что первые два охранника условия, которые у вас никогда не могут быть выполнены (те, где вы проверяете «str» от нуля или одной длины) –

1

На основе особенно полезный ответ от Чад Гилберт, и некоторые дополнительные лужения, я нашел способ иметь мой торт и съесть его. В случае, если кто имеет подобный камень преткновения, вот способ указать непокрытые случаев до объявляя ваши охранники:

myFun :: [Char] -> Char 
myFun "" = "" 
myFun [email protected](s:rst) 
     | rst == "" = s 
     | otherwise = myFun (s:rst) 

Это также работает с несколькими аргументами:

strSplit :: [Char] -> [[Char]] -> [[Char]] 
strSplit str [] = strSplit str [""] 
strSplit "" _ = [""] 
strSplit [email protected](s1:ns) [email protected](x:xs) 
     | s1 == '|' = strSplit ns ("":list) 
     | ns == "" = map reverse $ ((s1 : x) : xs) 
     | otherwise = strSplit ns ((s1 : x) : xs) 

Или с материалом, используя оригинальная [email protected](first:second:rest) идея:

lastTwo :: [Char]->[Char] 
    lastTwo "" = "" 
    lastTwo [x] = [x] 
    lastTwo [email protected](f:s:rst) 
      | rst =="" = [f,s] 
      | otherwise = lastTwo (s:rst) 

Это, вероятно, очень очевидно для людей более знакомы с Haskell, но я не понял, что вам было разрешено просто объявлять функцию несколько раз, используя другой синтаксис для покрытия различных случаев.

+0

Просто для удовольствия вам также может понравиться: 'lastTwo = reverse. возьмите 2. reverse'. –

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