Определил функцию без использования каких-либо языковых расширений, но должен ли он использовать языковое расширение для объявления его типа? - PullRequest
3 голосов
/ 10 февраля 2012

Я определил пользовательский тип ошибки, который я хочу использовать с монадой Ошибка. Для примера вот фиктивная:

newtype CustomError = CustomError String
instance Error CustomError where
  strMsg = CustomError

Я бы хотел определить функцию throwCustomError, которая работает как throwError, но вместо того, чтобы просто выбросить данную строку, она использует ее для создания CustomError, а затем выдает , которая, Это определение работает:

-- | Throws a 'CustomError' containing the given error message.
throwCustomError msg = throwError $ CustomError msg

Однако я хотел бы добавить объявление типа, главным образом, чтобы Хэддок включил описание функции в сгенерированную документацию. Если я использую :t в GHCI, это говорит мне, что тип этой функции MonadError CustomError m => String -> m a, и это имеет смысл для меня, но если я напишу

throwCustomError :: MonadError CustomError m => String -> m a

GHC жалуется на «аргумент не переменного типа» и говорит мне, что я должен использовать -XFlexibleContexts, чтобы разрешить его. Почему я должен использовать расширение языка для объявления функции этого типа, когда я могу определить функцию этого типа без использования каких-либо языковых расширений? Есть ли способ объявить тип этой функции без использования языковых расширений?


В отдельном примечании я первоначально попытался определить функцию как

throwCustomError = throwError . CustomError

но GHC говорит мне: «Нет экземпляра для (MonadError CustomError m0), возникающего в результате использования throwError». Я не совсем понимаю, почему это определение не эквивалентно другому; насколько я понимаю, они оба означают одно и то же.


Шаг назад: стоит ли мне вообще определять эту функцию? Или я должен просто написать throwError $ strMsg "foo", когда я хочу выдать ошибку? (В настоящее время у меня в коде throwError "foo", поэтому мне нужно изменить эти строки в любом случае.)

1 Ответ

1 голос
/ 10 февраля 2012

Поскольку вы используете монаду Error, вы уже полагаетесь на расширения, особенно на MultiParamTypeClasses и FunctionalDependencies, поэтому я не уверен, что есть смысл пытаться сохранить расширение вашего кода -бесплатно.

Существуют некоторые расширения, которые имеют некоторые потенциально неприятные побочные эффекты (например, IncoherentInstances), и, безусловно, есть смысл сводить их к минимуму, но такие расширения, как FlexibleContexts, абсолютно безвредны.

...