Как определить несколько паттернов во Фреге?

У меня возникли проблемы с определением функции в Frege, которая использует несколько шаблонов. По сути, я определяю сопоставление, перебирая список кортежей. Я упростил его до следующего:

foo :: a -> [(a, b)] -> b
foo _ [] = [] --nothing found
foo bar (baz, zab):foobar
 | bar == baz = zab
 | otherwise  = foo bar foobar

Я получаю следующую ошибку:

E morse.fr:3: redefinition of `foo` introduced line 2

Я видел и другие примеры, такие как этот которые используют несколько шаблонов в определении функции, поэтому я не знаю, что я делаю неправильно. Почему я получаю здесь ошибку? Я новичок в Frege (и новичок в Haskell), поэтому может быть что-то простое, что я упускаю, но я действительно не думаю, что это должно быть проблемой.

Я компилирую с версией 3.24-7.100.


person JJ Brown    schedule 11.02.2017    source источник
comment
Возможно, вам придется добавить скобки вокруг шаблона (baz, zab):foobar. Что-то вроде foo bar ((baz, zab):foobar)   -  person Alec    schedule 11.02.2017


Ответы (1)


Это чисто синтаксическая проблема, которая затрагивает новичков в языках семейства Haskell. Это не займет много времени, пока вы не усвоите правило, согласно которому приложение-функция имеет более высокий приоритет, чем инфиксное выражение.

Это имеет последствия:

  • Сложные аргументы приложения функции нуждаются в круглых скобках.
  • В инфиксных выражениях приложения функций по обе стороны от оператора не нуждаются в круглых скобках (однако отдельные компоненты приложения функции могут по-прежнему нуждаться в них).

Кроме того, у Фреге выполняется следующее правило:

Синтаксис применения функций и инфиксных выражений в левой части определения идентичен синтаксису в правой части в отношении лексем, разрешенных с обеих сторон. (Это справедливо в Haskell только тогда, когда @ и ~ не используются.)

Это значит, что вы можете определить функцию сложения следующим образом:

data Number = Z | Succ Number

a + Z      = a
a + Succ b = Succ a + b

Следовательно, когда вы применяете это к своему примеру, вы видите, что синтаксически вы собираетесь переопределить оператор :. Чтобы добиться того, чего вы хотите, вам нужно написать это так:

foo bar ((baz, zab):foobar) = ....
--      ^                 ^

Это соответствует ситуации, когда вы применяете foo к списку, который вы создаете:

foo 42 (x:xs)

Когда вы пишете

foo 42 x:xs

это означает

(foo 42 x):xs
person Ingo    schedule 11.02.2017
comment
Это имеет большой смысл. Спасибо за подробный ответ! - person JJ Brown; 18.02.2017