Для удовольствия Я создаю библиотеку синтаксического анализатора. В этой библиотеке у меня есть тип с Parser
данных:Тип Ограничения в Typeclass
data Parser e a = Parser (String -> Either e (a, String))
Я могу определить Functor
и Applicative
экземпляров Parser
, но я не думаю, что я могу сделать Alternative
экземпляра без ограничения типа «ошибки» или тип «значения», который может вернуть парсер. Первоначально это заставило меня создать экземпляр Applicative
для тех случаев, когда типы ошибок являются сообщениями String
, но я понял, что должен уметь освободить это ограничение для любого типа данных сообщений, который имеет экземпляр (или возможно Monoid
вместо?). Имея это в виду, я написал следующее:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
instance Alternative e => Alternative (Parser e)
where
empty = Parser $ \s -> Left empty
(<|>) (Parser p1) (Parser p2) = Parser $ \s -> tryParser s p2 $ p1 s
where
tryParser s p2 (Left _) = p2 s
tryParser _ _ x = x
К сожалению, это не скомпилировано. Когда я загрузить его в GHCI я получаю сообщение об ошибке:
Parsertest.hs:31:47:
Expecting one more argument to `e'
In the instance declaration for `Alternative (Parser e)'
Failed, modules loaded: none.
Когда я поиск в Интернете, это, кажется, решение, но это не работает для меня. Что мне не хватает?
Это заставляет вещи скомпилироваться снова. Знаете ли вы, где я могу читать, когда Monoid, Alternative, MonadPlus имеет смысл использовать? – chanko08
Wellllll, я написал [ответ] (http://stackoverflow.com/a/13115196/1598537) и [другой] (http://stackoverflow.com/a/13174738/1598537) по аналогичной теме ([здесь ] (http://stackoverflow.com/questions/13080606)), если вы довольны довольно теоретическими обсуждениями там. Если вы хотите получить более практические советы после прочтения их, вы можете попробовать задать это как новый вопрос, но будьте осторожны, чтобы было ясно, что вы их читали, и что вам нужно руководство для того, когда выбирать их, или если это незначительное разъяснение одного из этих ответов, спросите в комментарии. – AndrewC
@chanko Я должен был сказать, что Alternative _is_ подходит для парсера, в то время как Monoid имеет смысл для типа ошибки. – AndrewC