Вопрос

Мне просто интересно, можно ли несколько раз сопоставить одни и те же значения с помощью средств сопоставления шаблонов функциональных языков программирования (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)]}))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top