Присвоение переменных в haskell - PullRequest
0 голосов
/ 25 апреля 2018

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

getSpaces :: String -> String
getSpaces index = 
    if (length index) == 1 then index
    else
        if isInfixOf " " index then index = " "
        else index

Когда я пытаюсь загрузить свой модуль в GHCI, я получаю ошибку:

Prelude> :l Utilities
[1 of 1] Compiling Utilities        ( Utilities.hs, interpreted )

Utilities.hs:55:42: error:
parse error on input ‘=’
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
   |
55 |        if isInfixOf " " index then index = " "
   |                                          ^
Failed, no modules loaded.

Почему я не могу переназначить индекс на один пробел?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Почему я не могу переназначить индекс на один пробел?

Потому что в Хаскеле вы не можете ничего переназначить. На самом деле вы никогда даже не назначаете , вы объявляете (это что-то связанное, но другое). Даже в некоторых случаях, когда это может выглядеть так, как будто вы переназначаете переменные (как в do блоках, вы не переназначаете, но вы shadow переменные объявляете новую переменную с тем же именем, опять же, это немного связано, но во многих случаях мы видим другое поведение, например, в цикле мы не можем скрывать переменную каждую итерацию).

Чтобы ответить на ваш вопрос, вы, вероятно, захотите вернуть строку с одним пробелом, мы можем сделать это, написав:

getSpaces index = if (length index) == 1 then index else
                                 if isInfixOf " " index then <b>" "</b> else index

Но, тем не менее, это все еще довольно не элегантно, а также довольно небезопасно, поскольку в случае бесконечного String это начнет циклически повторяться: length продолжает циклировать, пока список (символов) не будет исчерпан, и Вполне возможно, что этого никогда не произойдет. Более того, даже если он не застревает в бесконечном цикле, он все равно не рекомендуется, поскольку он работает в O (n) n длиной списка). Так что для длинных списков это неэффективно.

Обычно в Haskell используется комбинация шаблонов и охранников , чтобы различать возможные значения. Ваш случай может быть сопоставлен с:

getSpaces :: String -> String
getSpaces st@[_] = st
getSpaces st | isInfixOf " " st = st
             | otherwise = " "

Это все равно будет зацикливаться, однако, если список имеет бесконечный размер, sinze isInfixOf продолжает искать пробел, пока не найдет его, или String не будет исчерпан.

Поскольку isPrefixOf с шаблоном поиска в виде строки с одним символом фактически означает, что мы смотрим, если строка содержит пробел, мы можем заменить это на elem и искать символ ' ':

getSpaces :: String -> String
getSpaces st@[_] = st
getSpaces st | elem ' ' st = st
             | otherwise = " "
0 голосов
/ 25 апреля 2018

Я нашел исправление, вместо изменения индекса, я просто возвращаю один пробел.

Insead of:

if isInfixOf " " index then index = " "

Я сделал:

if isInfixOf " " index then " "

Так что я просто вернул пробел.

...