Рассмотрим следующий код:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class X a
class Y a
instance Y Bool
instance (Y a) => X a
instance {-# OVERLAPPING #-} X Int
f :: (X a) => a -> a
f x = x
Эти прагмы ЯЗЫКА необходимы для написания приведенных выше примеров.
Теперь, скажем, мы хотим написать функцию g:
g :: (Y a) => a -> a
g = f
Без IncoherentInstances или добавления {- # INCOHERENT # -} в один из экземпляров, это не проверка типов. Но когда мы добавим это и спросим ghci
ghci> :t f
f :: Y a => a -> a
Внезапно тип 'f' изменился?
В этом небольшом примере программы все еще проверяют тип, когда я задаю f Int (указывая что вышеупомянутое было бы просто «визуальной ошибкой», но в более крупном примере то же самое не проверяет тип, давая мне ошибку вроде:
Could not deduce (Y a) arising from a use of 'f
(...)
from the context: (..., X a, ...)
Это также происходит, когда мы говорим
h = f
и попробуйте позвонить h с Int