Проблема с сильной типизацией при сопоставлении с образцом - PullRequest
0 голосов
/ 14 октября 2019

Я хочу написать рекурсивную функцию, которая использует сопоставление с образцом. Я хочу вызвать его с помощью строки массива (как, например, та ["01!", "1 !!?", "?! 1"]). Если заголовок первого элемента равен 1, функция должна выйти, если заголовок равен 0, она должна удалить элемент из списка, и если этот элемент равен? или же ! он должен перезапустить функцию со следующей строкой массива (позже будет другая функция, я просто хочу, чтобы она работала до сих пор).

may_convergent:: [[Char]] -> String
may_convergent [] = "empty list"
may_convergent (x:xs)
       | head x == "1" = "May-convergent "
       | head x == "0" = tail x
       | otherwise = may_convergent xs

Это мой код. Когда я выполняю его, я получаю ошибку типизации. Может кто-нибудь объяснить мне, как я правильно понял Типизацию в первой строке Кодекса? Сообщение об ошибке говорит, что ожидаемый тип [[[Char]]], но когда я исправляю типизацию и вызываю функцию, она не работает.

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

Ответы [ 2 ]

3 голосов
/ 14 октября 2019

Проблема не в системе типов. Но с вашими чеками. Если вы напишите:

<b>head</b> x == "1"

Haskell выведет, что тип head x должен быть String, и, следовательно, x должен быть [String]. Но поскольку x является первым элементом вашего списка, это String, а не [String]. Вы можете исправить это, сравнивая с символом, например:

head x == <b>'1'</b>

Однако мы можем использовать здесь сопоставление с образцом, делая код не только более элегантным, но и более безопасным. Например, даже если ваш текущий код скомпилируется, это вызовет ошибку на [""], поскольку head "", конечно, не имеет смысла.

Мы можем определить функцию, подобную:

may_convergent:: [[Char]] -> String
may_convergent [] = "empty list"
may_convergent ((<b>'1'</b>:_):_) = "May-convergent "
may_convergent ((<b>'0'</b>:xs):_) = xs
may_convergent (_:xs) = may_convergent xs
3 голосов
/ 14 октября 2019

Вот типы участвующих величин:

x :: [Char]
head x :: Char
"1" :: String

, следовательно, head x == "1" пытается сравнить символ и строку. Правильно типизированное сравнение будет

head x == '1'

, поскольку у нас есть '1' :: Char.

При этом обратите внимание, что head x вылетит, когда x пусто. По этой причине лучше избегать использования head и tail и вместо этого использовать сопоставление с образцом.

may_convergent:: [[Char]] -> String
may_convergent []            = "empty list"
may_convergent (('1':_ ):_ ) = "May-convergent "
may_convergent (('0':ys):_ ) = ys
may_convergent (_       :xs) = may_convergent xs
...