To naprawdę bardzo proste. Zapytajmy GHCi jaki rodzaj isList2
jest:
∀x. x ⊢ :t isList2
isList2 :: a -> Bool
To nie pasuje do instancji [a]
(choć mógł, poprzez zjednoczenie), ale nie od razu dopasować instancji a
. Dlatego GHC wybiera instancję a
, więc isList2
zwraca False
.
To zachowanie jest dokładnie tym, co oznacza IncoherentInstances
. Właściwie jest to raczej niezła demonstracja tego.
Hilariously, jeśli po prostu wyłączyć IncoherentInstances
otrzymujemy dokładnie odwrotny skutek, a GHCi teraz mówi tak:
∀x. x ⊢ :t isList2
isList2 :: [Integer] -> Bool
Dzieje się tak dlatego isList2
jest wiążącym najwyższego poziomu nie określono przy użyciu składni funkcji , a tym samym podlega ograniczeniu Mormorphism. Więc specjalizuje się w instancji, z którą jest faktycznie używana.
Dodawanie NoMonomorphismRestriction
jak również wyłączenie IncoherentInstances
, otrzymujemy zamiast tego:
∀x. x ⊢ :t isList2
isList2 :: IsList a => a -> Bool
∀x. x ⊢ isList2 'a'
False
∀x. x ⊢ isList2 "a"
True
∀x. x ⊢ isList2 undefined
<interactive>:19:1:
Overlapping instances for IsList a0 arising from a use of `isList2'
Jaki jest spodziewany nakładających zachowanie, za przykład wybranego na podstawie użytkowania i reklamacji, jeśli wybór jest niejednoznaczny.
Jeśli chodzi o edycję tego pytania, nie wierzę, że pożądany wynik jest możliwy bez adnotacji typu.
Pierwszą opcją jest nadanie isList2
podpisu typu, który uniemożliwia IncoherentInstances
wybieranie instancji zbyt wcześnie.
isList2 :: (IsList a) => a -> Bool
isList2 = isList
Prawdopodobnie będziesz musiał zrobić to samo nigdzie indziej isList
jest wymienione (nawet pośrednio) nie są stosowane do kłótni.
Drugą opcją jest ujednoznacznienie literałów numerycznych i wyłączenie IncoherentInstances
.
main =
print (isList (42 :: Integer)) >>
print (isList2 (42 :: Integer)) >>
print (isList [42]) >>
print (isList2 [42])
W tym przypadku, nie ma wystarczająco dużo informacji, aby wybrać najbardziej konkretny przypadek, więc OverlappingInstances
robi jego rzecz.
Ponieważ program jest niespójny. Naprawdę, czego oczekiwałeś *? –
Oczekiwalem, że wyjście będzie "True True", a nie "True False". Dlaczego oczekujesz, że wynik będzie "True False"? Dlaczego niespójny program nie powróci do "Prawdziwej Prawdy"? Czy mówisz, że nie ma powodu dla wyjścia, a wynik jest nieokreślony i czasami może on zwracać "True True"? – Clinton
prawdopodobny duplikat [Jak działa IncoherentInstances?] (Http://stackoverflow.com/questions/8371499/how-does-incoinneinstrukcje-work) –