Можно ли использовать Pattern Matching для членства в списке? - PullRequest
0 голосов
/ 02 марта 2020

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

-- Using guards
f :: [Int] -> Int
f xs
    | 42 `elem` xs = 42
    | otherwise = 0

-- Using pattern matching?
g :: [Int] -> Int
g (_:)*42:_ = 42  -- i.e. zero or more elements: we discard until 42, followed by whatever.
g _         = 0

Ответы [ 5 ]

6 голосов
/ 02 марта 2020

Да. Только с буквальными значениями Int; рекурсивно.

-- Using pattern matching alone
g :: [Int] -> Int
g (42:_) = 42 
g []     = 0
g (_:r)  = g r

Тестирование:

> g [1..50]
42

> g [1]
0

Хотя в шаблонах нет регулярных конструкций. Я бы sh мог бы написать что-то вроде

foo [...xs, 42, ...ys] = xs ++ ys
foo _ = []

, но мы не можем.

Обновление: после предложения @ chi в комментарии ; используя просмотр шаблонов ;

{-# LANGUAGE ViewPatterns #-}

g2 (break (== 42) -> (_,[])) = 0   -- 0,  if not found
g2 _ = 42                          -- 42, otherwise

Я не уверен, считается ли он «только шаблонами», поскольку он использует «обычную» стандартную функцию, break. Преимущество в том, что это больше не только с литералами.

3 голосов
/ 02 марта 2020

короткий ответ: нет
длинный ответ:
шаблоны определены рекурсивно следующим образом:

pattern := variable
         | constant
         | C p1 p2... where C is a constructor and p1 p2... are patterns
         | variable@pattern
2 голосов
/ 02 марта 2020

Вы можете, в некотором роде, но для этого нужно включить расширение GH C.

{-# LANGUAGE ViewPatterns -#}

g :: [Int] -> Int
g ((42 `elem`) -> True) = 42
g _         = 0

Шаблон вида f -> v соответствует аргументу x, если f x соответствует v.

2 голосов
/ 02 марта 2020

Можно ли использовать сопоставление с образцом для членства в списке?

Только путем рекурсивного применения шаблонов, например,

elem :: Eq a => a -> [a] -> Bool
elem x [] = False
elem x (y:ys) = x == y || elem x ys

Так что ни один из шаблонов [] и y:ys сами проверяют членство в списке.

Но в сочетании с рекурсией они играют важную роль.

0 голосов
/ 02 марта 2020

"Ноль или более элементов, которые мы отбрасываем до 42, а затем все что угодно."

Нет.

Этот шаблон будет соответствовать только спискам с 42 в качестве второго элемента. : - это конструктор списка, который создает \ декомпозирует список уникальным способом, а не конкатенацией, и конкатенация «сложна» для использования при сопоставлении с образцом.

...