Я ответил на аналогичный вопрос от вас здесь, в кафе .
Как говорит @Carl, все экземпляры должны находиться везде в области видимости. Исключением является компиляция так называемых 'сиротских экземпляров' - что является плохой вещью и ее легко избежать.
Для записи здесь, подход заключается в использовании Ассоциированного типа в вашем классе с определением по умолчанию. Это работает, если вы искренне рады, что тип Associated сгенерировал ошибку «no instance», если нет соответствия ограничению:
class A t where
type MatchesA t :: Bool -- Associated type
type instance MatchesA t = True -- default instance
... -- methods for A
instance A Int where
-- uses default instance for MatchesA
... -- method implementations as usual
-- undefined :: (MatchesA Int) -- gives type True
-- undefined :: (MatchesA Bool) -- gives 'no instance' error
Я думаю, вы можете получить ограничение - или Matches - см. Сообщение в кафе для MatchesA или MatchesB. (Я быстро это проверил, это может быть немного странно, в зависимости от того, насколько нетерпеливым является сокращение семейства типов.)
То, что вы не можете сделать с этим подходом, - это выбрать одну вещь, если ограничение выполняется, и другую, если это не так. Таким образом, лучшее, что вы можете получить, это «не уменьшить». В посте кафе я ссылаюсь на (довольно старую) вики-страницу с более всесторонним подходом, который опирается на перекрывающиеся экземпляры. Связанные типы не допускают перекрытий: - (.
РЕДАКТИРОВАТЬ: Существует глубокая причина, по которой компилятор не показывает, соответствует ли какое-либо ограничение, как вы хотите для Prelude
классов в вашем комментарии: вы можете использовать факт соответствия с выберите какой-нибудь экземпляр другого класса C
; и может существовать еще один класс D
, выбор экземпляра которого зависит от совпадения C
; и выбор экземпляра A, B
зависит от D
. Так что теперь у нас есть круговые зависимости. Это может быть осложнено другими экземплярами в других модулях, которые компилятор еще не видел.
Таким образом, все эти (очевидно) дублированные экземпляры на вики-странице представляют, что программист знает все экземпляры и как они взаимозависимы, таким образом, что компилятор не может понять.