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