Как работают IncoherentInstances?

Игра с неким кодом :

{-# 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

В чем заключается черная магия, стоящая за несогласованными экземплярами? Почему он делает то, что здесь?

35
задан Community 23 May 2017 в 12:26
поделиться