Ответ 1
Это невозможно в Haskell из-за так называемого "Углеродного мира". В нем указано, что набор экземпляров для классов типов открыт, что означает, что вы можете создавать новые экземпляры в любое время (в отличие от закрытого мира, где должен быть фиксированный набор экземпляров). Например, в то время как класс Functor
typeclass определен в Prelude, я все же могу сделать экземпляры для него в моем собственном коде, который не находится в Prelude.
Чтобы реализовать то, что вы предложили, компилятору нужен способ проверить, является ли тип T
экземпляром класса C
. Это, однако, требует, чтобы компилятор знал все возможные экземпляры этого класса, и это невозможно из-за предположения открытого мира (при компиляции Prelude компилятор еще не знает, что вы позже сделаете YourOwnFunctor
экземпляр Functor
тоже).
Единственный способ заставить его работать - это рассмотреть только экземпляры, которые в настоящее время видны (потому что они были определены в текущем модуле или любом его импорте). Но это приведет к совершенно непредсказуемому поведению: набор видимых экземпляров зависит не только от импорта модуля, но и от импорта импорта, поскольку вы не можете скрывать экземпляры. Таким образом, поведение вашего кода будет зависеть от деталей реализации ваших зависимостей.
Если вы хотите закрытый мир, вы можете вместо этого использовать закрытые типы семейств, которые были введены в GHC 7.8. Используя их, вы можете написать:
type family Equal a b :: Bool where
Equal x x = True
Equal x y = False