Предположим, что у меня есть это семейство типов, которое выдает ошибку настраиваемого типа во время компиляции, если переданный ему тип не является записью:
type family IsRecord (a :: Type) where
...
Теперь у меня есть этот класс типа, который имеет методы с реализациями по умолчанию, но требует, чтобы тип был записью, добавив ограничение IsRecord
:
class IsRecord a => Foo a where
foo :: Text
foo = "foo"
При попытке использовать его неправильно, если мы используем его как обычный экземпляр с типом, который не является записью, он успешно не компилируется:
data Bar = Bar
instance Foo Bar -- error: Bar is not a record
Но если я включу -XDeriveAnyClass
и добавлю его к производному предложению, это не приведет к отказу от компиляции, полностью игнорируя ограничение:
data Bar = Bar
deriving (Foo)
Я понимаю, что DeriveAnyClass
генерирует пустое объявление экземпляра, что я и делаю в первом примере, но по-прежнему не вызывает ошибки. Что происходит?
Я использую GHC 8.6.4
instance IsRecord Bar => Foo Bar
. - person Willem Van Onsem   schedule 14.06.2019IsRecord Bar
выполняется, тогда мы можем определитьinstance Foo Bar
, как указано в этом экземпляре. На данный момент это ограничение не выполняется, если вы позже добавите экземпляр, например, в другой модуль, тогда ограничение будет истинным, и, следовательно, вы получите экземпляр. Таким образом, это добавляет дополнительную гибкость. - person Willem Van Onsem   schedule 14.06.2019instance HasCallStack => PrintStack
, которые, таким образом, доступны, если система использует стек вызовов. Таким образом, этот экземпляр доступен только тогда. - person Willem Van Onsem   schedule 14.06.2019