Сопоставление с образцом для равенства

parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed c dp -> Parsed c dp
      _ -> NoParse

Вышеупомянутая функция должна принимать Char c и возвращать Parser, который будет соответствовать только c. Функция dvChar d вернет либо Parsed char dp, либо NoParse (где char — следующий символ в строке). Таким образом, я надеялся, что Parsed c dp будет соответствовать только результату, в котором char==c, но на самом деле происходит то, что синтаксический анализатор, возвращаемый этой функцией, соответствует любому символу (даже несмотря на то, что c кажется привязанным к какому-то конкретному символу Char). , как аргумент функции).

Следующая функция работает корректно:

parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed char dp -> if char == c then Parsed char dp else NoParse
      _ -> NoParse

Ручное кодирование синтаксического анализатора для разбора буквы 'a' также работает корректно, в этом

case dvChar d of
   Parsed 'a' dp -> Parsed 'a' dp
   _ -> NoParse

вернет успех только в том случае, если символ был 'a'.

Так что дает? Можете ли вы сопоставлять литералы только по такому шаблону (например, несмотря на то, что Char находится в классе Eq, if char==c (..) все равно нужно кодировать вручную), или я делаю что-то не так?


person Pete    schedule 19.07.2010    source источник
comment
Между прочим, правило единственного соответствия конструкторов, безусловно, хорошая вещь, потому что в противном случае импорт нового определения верхнего уровня (скажем) может сильно изменить семантику фрагмента кода!   -  person Reid Barton    schedule 22.07.2010


Ответы (1)


Да, вы можете сопоставлять только литералы. На самом деле, лучший способ думать об этом состоит в том, что вы можете сопоставлять только конструкторы, и так уж получилось, что Int, Char, String & co. у всех есть буквальные конструкторы.

Обратите внимание, что вы также можете смешивать регистр и охрану и писать как (по памяти):

parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed char dp | char == c -> Parsed char dp
      _ -> NoParse
person sclv    schedule 19.07.2010