Игра с неким кодом :
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
class Arity f where
arity :: f -> Int
instance Arity x where
arity _ = 0
instance Arity f => Arity ((->) a f) where
arity f = 1 + arity (f undefined)
Без IncoherentInstances
:
ghci> arity foldr
blah blah ambiguous blah blah possible fix blah
ghci> arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)
3
ghci> let f x y = 3 in arity f
2
ghci> arity $ \x y -> 3
2
Если мы добавим IncoherentInstances
в список прагм , то он может обрабатывать foldr
без необходимости использования сигнатуры мономорфного типа, но он получает неправильный ответ на лямбда-выражения:
ghci> arity foldr
3
ghci> let f x y = 3 in arity f
2
ghci> arity $ \x y -> 3 -- should be 2
0
В чем заключается черная магия, стоящая за несогласованными экземплярами? Почему он делает то, что здесь?