Шаблон, соответствующий идентичным значениям
-
19-09-2019 - |
Вопрос
Мне просто интересно, можно ли несколько раз сопоставить одни и те же значения с помощью средств сопоставления шаблонов функциональных языков программирования (Haskell/F#/Caml).
Просто подумайте о следующем примере:
plus a a = 2 * a
plus a b = a + b
Первый вариант будет вызываться, когда функция вызывается с двумя одинаковыми значениями (которые будут храниться в a
).
Более полезным применением было бы это (упрощение AST).
simplify (Add a a) = Mult 2 a
Но Haskell отвергает эти коды и предупреждает меня о противоречивые определения a
- Вместо этого мне приходится выполнять явную проверку регистра/если, чтобы выяснить, получила ли функция идентичные значения.Есть ли какой-нибудь трюк, позволяющий указать, что переменная, которую я хочу сопоставить, будет встречаться несколько раз?
Решение
Это называется нелинейный узор.Не так давно в списке рассылки haskell-cafe было несколько тем по этому поводу.Вот два:
http://www.mail-archive.com/haskell-cafe@haskell.org/msg59617.html
http://www.mail-archive.com/haskell-cafe@haskell.org/msg62491.html
Нижняя граница:это не невозможно реализовать, но было решено отказаться ради простоты.
Кстати, тебе не нужно if
или case
обойти это;(немного) более чистый способ — использовать защиту:
a `plus` b
| a == b = 2*a
| otherwise = a+b
Другие советы
Вы не можете иметь два параметра с одинаковым именем, чтобы указать, что они должны быть равны, но вы можете использовать охранники чтобы различать такие случаи:
plus a b
| a == b = 2 * a
| otherwise = a + b
Это более гибко, поскольку работает и для более сложных условий, чем простое равенство.
Я только что просмотрел ветки списка рассылки, приведенные в ответе Томаса, и самый первый ответ в одном из них имеет смысл и объясняет, почему такой «шаблон» в целом не имеет особого смысла: что, если a
это функция?(Вообще-то проверить равенство двух функций невозможно.)
Haskell не выполняет унификацию.
Я реализовал новый функциональный язык программирования, который может обрабатывать нелинейные шаблоны в Haskell.
https://github.com/egison/egison
На моем языке ваш plus
функция записана следующим образом.
(define $plus
(match-lambda [integer integer]
{[[$a ,a] (* a 2)]
[[$a $b] (+ a b)]}))