4

Zu der Zeit, als ich zum ersten Mal ernsthaft criticism on -XUndecidableInstances gelesen hatte, hatte ich mich bereits daran gewöhnt, sah es als nur Beseitigung einer lästigen Einschränkung Haskell98 muss Compiler einfacher zu implementieren machen.Wie kann unentscheidbare Instanzen den Compiler tatsächlich hängen?

In der Tat habe ich viele Anwendungen angetroffen, wo unentscheidbare Instanzen benötigt wurden, aber keine, wo sie tatsächlich irgendwelche Probleme im Zusammenhang mit Unentscheidbarkeit verursacht. Lukes Beispiel ist problematisch, aus einem ganz anderen Grunde

class Group g where 
    (%) :: g -> g -> g 
    ... 
instance Num g => Group g where 
    ... 

- na ja, das deutlich überlappt wäre durch eine geeignete Group Instanz, so Unentscheidbarkeit ist die geringste unserer Sorgen: das ist eigentlich un determinis!

Aber fair genug, ich habe seit "unentscheidbar Instanzen kann den Compiler hängen" in meinem Hinterkopf.

Woher es beschafft wurde, als ich this challenge on CodeGolf.SE las und nach Code fragte, der den Compiler unendlich hängen würde. Klingt wie ein Job für unentscheidbare Instanzen, oder?

Stellt sich heraus, ich kann sie nicht dazu bringen, es zu tun. Die folgende compiliert in kürzester Zeit, zumindest von GHC-7.10:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 
class C y 
instance C y => C y 
main = return() 

ich auch Klassenmethoden verwenden kann, und sie werden dazu führen, nur eine Schleife bei Laufzeit:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 
class C y where y::y 
instance C y => C y where y=z 
z :: C y=>y; z=y 
main = print (y :: Int) 

Aber Laufzeit Schleifen sind nichts Ungewöhnliches, Sie können diese einfach in Haskell98 codieren.

Ich habe auch versucht, andere, weniger direkte Schleifen wie

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-} 
data A x=A 
data B x=B 
class C y 
instance C (A x) => C (B x) 
instance C (B x) => C (A x) 

Wieder kein Problem bei der Kompilierung.

Also, was ist eigentlich erforderlich, um den Compiler in der Auflösung von Klassen Instanzen von undecidable Typ aufhängen?

+0

Wahrscheinlich müssen Sie etwas tun, damit der Compiler entscheidet, ob 'Int' eine Instanz von' C' ist. – immibis

Antwort

10

Ich glaube nicht, dass ich jemals den Compiler aufgehängt habe. Ich kann es jedoch zum Stack-Überlauf bringen, indem ich das erste Beispiel modifiziere. Es scheint, dass etwas Caching vor sich geht, so dass wir eine unendliche Sequenz von eindeutigen Einschränkungen, z.

data A x = A deriving (Show) 
class C y where get :: y 
instance (C (A (A a))) => C (A a) where 
    get = A 

main = print (get :: A()) 

die uns

• Reduction stack overflow; size = 201 
    When simplifying the following type: 
    C (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A (A()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 
    Use -freduction-depth=0 to disable this check 
    (any upper bound you could choose might fail unpredictably with 
    minor updates to GHC, so disabling the check is recommended if 
    you're sure that type checking should terminate) 

gibt, die Ihnen sagt, wie Sie es hängen bekommen könnte, wenn man wirklich wollte. Meine Vermutung ist, dass Sie einen Fehler gefunden haben, wenn Sie es ohne dieses Problem aufhängen können.

Ich würde gerne von jemandem hören, der auf GHC arbeitet.

6

Der einfachste Weg, um einen „Reduktion Stapelüberlauf“ wird mit Typ Familien zu bekommen:

type family Loop where 
    Loop = Loop 

foo :: Loop 
foo = True 

Ich weiß nicht, einen direkten Weg tatsächlich Looping Kompilierung auf dem aktuellen GHC zu bekommen. Ich erinnere mich, dass ich mit GHC 7 Loops mehrmals erhalten habe.11, aber ich erinnere mich nur an eine in reproduzierbaren Details:

data T where 
    T :: forall (t :: T). T 

Aber das wurde seit behoben.

2

Zu meiner Überraschung kann UndecidableInstances tatsächlich bestimmte GHC-Versionen hängen. Hier sind die wenigen Codezeilen, die es für mich getan hat:

{-# LANGUAGE FlexibleInstances  #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE TypeFamilies   #-} 
{-# LANGUAGE UndecidableInstances #-} 
module Nested where 

class Nested r ix where 

type family Lower ix :: * 

data LN 

instance Nested LN (Lower ix) => Nested LN ix where 

data L 

instance Nested LN ix => Nested L ix where 

Wenn sie als Teil einer Bibliothek zusammengestellt (nicht direkt ghc main.hs) Dieser Code hängt auf unbestimmte Zeit auf GHC 8.2.1

Wie @luqui erwähnt, dies ist wie ein Bug scheint, so hat es sich als solche berichtet: https://ghc.haskell.org/trac/ghc/ticket/14402

bearbeiten: es stellte sich heraus, um einen Fehler in der Tat, die in der aktuellen Entwicklungsversion von GHC Fest bereits wurde.

Verwandte Themen