Попытка написать функцию на Haskell и в соответствии с -Wall мне нужен шаблон, который соответствует (_: _: _) _ Что означает этот шаблон и зачем он мне нужен? - PullRequest
0 голосов
/ 01 июня 2018

Итак, я хотел попробовать сделать эту функцию сам (умножает все в списке на 3 и возвращает новый список):

list = [1,2,3,4,5,6,7,8,9,10]
list2 = [3 * x | x <- list]

И мне удалось получить это с помощью охранников (в основном это останавливается, когдах достигает границы списка):

tripleMultList :: [Int] -> Int -> [Int]
tripleMultList lst x
   | null lst = []
   | length lst - 1 == x = (lst !! x * 3) : []
   | otherwise = (lst !! x * 3) : tripleMultList lst (x + 1)

Тогда я решил попробовать сделать это с сопоставлением с образцом:

tripleMultList :: [Int] -> Int -> [Int]
tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)

Но всякий раз, когда я пытался запустить эту функцию, яполучит неисчерпывающую ошибку сопоставления с образцом, поэтому я проверил ghci -Wall и он сказал, что мне нужен шаблон, сопоставленный с

(_:_:_) _ 

, который, как я предполагаю, примет форму

tripleMultList (_:_:_) _ = something

Я знаю, что

(_:_:_)

имеет отношение к выбору элементов из списка и отделению их от самого списка, хотя я понятия не имею, почему это применимо к моей функции.Я также не знаю, что означает «_» и как это относится к моей функции.

Поэтому я предполагаю, что мой вопрос заключается в том, что означает этот шаблон и зачем он мне нужен, когда у меня примерното же самое в версии моей функции, которая использует охрану, и что работает нормально?

Ответы [ 2 ]

0 голосов
/ 02 июня 2018

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

 data [] a = [] | a : [] a

Существует только два шаблона, которые необходимо сопоставить: пустой список ([]) и непустой список (x:y).У вас правильный регистр пустого списка: при умножении каждого элемента пустого списка получается другой пустой список.

tripleMultList [] = []

Для непустого списка вам нужно что-то немного более сложное.У вас есть первый элемент x, а остальные элементы - y.Все, что вам нужно сделать, это умножить x на 3 и добавить его в список, полученный умножением всего в y на 3:

tripleMultList (x:y) = let x' = 3 * x
                           y' = tripleMultList y
                       in x' : y'

Обратите внимание, что мы можем обобщить это для любой операции на x:

doSomething :: (a -> b) -> [a] -> [b]
doSomething _ [] = []
doSomething f (x:y) = let x' = f x
                          y' = doSomething f y
                      in x' : y'

tripleMultList = doSomething (\x -> 3 * x)

Этот тип операции настолько распространен, что doSomething уже определен в Haskell, но вместо этого он называется map.

0 голосов
/ 01 июня 2018

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

tripleMultList (_:_:_) _

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

Посмотрите на определенные вами случаи:

tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)

То есть:

  • Первый аргумент: пустой список;второй аргумент: что угодно.
  • первый аргумент: список с одним элементом;второй аргумент: что угодно;только если x == (length [y] - 1) истинно.
  • Первый аргумент: список с одним элементом;второй аргумент: что угодно;только если указанное выше условие не выполняется.

Это исключает случай, когда первый аргумент является списком, по крайней мере, с двумя элементами.

Если вы хотите выполнить декомпозицию вваше первое определение, тогда вам нужно использовать y во втором и третьем определениях вместо [y].Шаблон y (переменная) соответствует чему-либо (правильного типа) и дает ему имя y.Шаблон [y] соответствует любому списку одного элемента и дает этому элементу имя y.

...