Играя с некоторым кодом:
{-# 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
, не нуждаясь в мономорфной сигнатуре типа, но получает неправильный ответ на lambdas:
ghci> arity foldr
3
ghci> let f x y = 3 in arity f
2
ghci> arity $ \x y -> 3 -- should be 2
0
Что такое черная магия за Incoherent Instances? Почему он делает то, что здесь делает?