2016-05-01 4 views
1

Я пишу небольшую программу, которая «строит» строку из другой строки (которая является «входной строкой» (параметр)). Однако я получаю ошибку синтаксического анализа (на входе '='). Я подозреваю, что я делаю что-то не так с моим защитным выражением?Неверно в моем выражении охраны?

checkCons :: Char -> Bool 
checkCons x = notElem x ['a','e','i','o','u','y'] 


rovarSprak :: [Char] -> [Char] -> [Char] 
rovarSprak [] res = res 
rovarSprak (c:restOfStr) res 
    | (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res) 
    | otherwise = rovarSprak restOfStr (c:res) 

Если я позвоню: rovarSprak "abc" []. Я ожидаю "abobcoc".

Обратите внимание, что функция checkCons работает по желанию.

ответ

1

Я думаю, что ваш старый код не был должным образом отступом. Если я бегу ghc компилятор на:

rovarSprak :: [Char] -> [Char] -> [Char] 
rovarSprak [] res = res 
rovarSprak (c:restOfStr) res 
| (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res) 
| otherwise = rovarSprak restOfStr (c:res) 

он дает ошибку:

strep.hs:8:1: parse error on input ‘|’ 

переписывания это:

rovarSprak :: [Char] -> [Char] -> [Char] 
rovarSprak [] res = res 
rovarSprak (c:restOfStr) res 
    | (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res) 
    | otherwise = rovarSprak restOfStr (c:res) 

решает ошибку компиляции.

Кроме того Если попытаться воспроизвести его, результат:

"cocboba" 

Охранники работают отлично, единственная проблема с вашим кодом является то, что в рекурсивном вызове:

rovarSprak restOfStr (c:'o':c:res) 
--     ^push in front 

вы нажимаете результат перед новым списком, тогда как вы, вероятно, хотите, чтобы он был на хвосте.

Вы можете решить эту проблему, не работая с аккумулятором , но сразу же испускаете элементы. Например:

 
rovarSprak :: [Char] -> [Char] 
rovarSprak [] = [] 
rovarSprak (c:restOfStr) 
    | (checkCons c) == True = c : 'o' : c : (rovarSprak restOfStr) 
    | otherwise = c : rovarSprak restOfStr 

(выделение жирным шрифтом и штрих-кодом избыточных элементов кода). Это также позволяет создавать ленивые списки: возможно, вас интересуют только первые три элемента вывода, или, может быть, вход представляет собой бесконечный список.

Окончательный оптимизации я предлагаю поменять местами две строки rovarSprak:

 
rovarSprak :: [Char] -> [Char] 
rovarSprak (c:restOfStr) 
    | checkCons c = c : 'o' : c : (rovarSprak restOfStr) 
    | otherwise = c : rovarSprak restOfStr 
rovarSprak [] = [] 

это происходит потому, что он, скорее всего, вы будете иметь матч на первой линии: для списка с длиной N будет N звонки по первому рисунку и один на втором рисунке.

+0

@ J.doe: Вы намеревались использовать свой код, вероятно, как в редактировании? В противном случае, возможно, есть элемент в коде, о котором вы забыли упомянуть. –

+0

Проблема заключается в том, что не видно из моего примера кода (поскольку он был отредактирован), что emacs не отступает от охранников (и я даже не могу их табулировать), в фактах, которые мои охранники выровнены с: rovarsprak - это почему я получаю ошибку синтаксического анализа? а не «cocboba» @Willem Van Onsem –

+0

«Окончательная оптимизация» ничего не сделает. GHC * always * перестраивает шаблоны в соответствии с порядком, в котором конструкторы * определены *. Да, это иногда несчастливо, но так оно и есть в настоящее время. – dfeuer

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