2016-02-03 12 views
8

Gibt es einen Grund, warum dieser Code nicht kompiliert wird:Warum konnte der Compiler den Typ 'a == a' nicht mit 'True' für die Typfamilie vergleichen?

type family Foo a b :: Bool where 
    Foo a b = a == b 

foo :: Foo a b ~ True => Proxy a -> Proxy b 
foo _ = Proxy 

bar :: Proxy a -> Proxy a 
bar = foo 

mit Fehler:

Couldn't match type ‘a == a’ with ‘'True’ 
Expected type: 'True 
    Actual type: Foo a a 

aber wenn ich Typ Familie Definition

type family Foo a b :: Bool where 
    Foo a a = True 
    Foo a b = False 

es kompiliert gut ändern?

(GHC-7.10.3)

+5

Wo ist die Typfamilie '==' definiert? Wird es von Instanzen automatisch von GHC aufgehoben? Wenn dies der Fall ist, muss GHC die Möglichkeit einer merkwürdigen Instanz berücksichtigen, bei der bei einem benutzerdefinierten Typ '(==) = \ _ _ -> False', denke ich. – chi

+1

Können Sie ein vollständiges Arbeitsbeispiel hinzufügen? Wenn ich Ihr Beispiel versuche, erhalte ich andere Fehler als die, die Sie gezeigt haben. –

+2

@chi, oder nicht seltsam: '(Lassen Sie x = 0/0 in x == x) ~> False'. – user3237465

Antwort

9

Aufgrund einer Anfrage für ein komplettes Arbeitsbeispiel von Daniel Wagner, fand ich eine Antwort.

Komplettes Beispiel zuerst:

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE UndecidableInstances #-} 
{-# LANGUAGE PolyKinds #-} 
module Test where 

import Data.Type.Equality(type (==)) 
import Data.Proxy(Proxy(..)) 

type family Foo a b :: Bool where 
    Foo a b = a == b 

foo :: Foo a b ~ True => Proxy a -> Proxy b 
foo _ = Proxy 

bar :: Proxy a -> Proxy a 
bar = foo 

Das Problem hier ist mit PolyKinds Pragma. Ohne es geht es gut. Ich brauche es wahrscheinlich so, dass ich

bar :: Proxy (a :: *) -> Proxy a 

schreiben und alles gut geht.

Der Grund ist jetzt klar. Die Typfamilie (==) hat keine poly-kinded Instanzen (Details, die erklären, warum solche Instanzen nicht zur Verfügung gestellt werden here), so dass wir nicht alle Gleichheiten reduzieren können. Also müssen wir eine Art angeben.

+0

@haoformayor Wenn Sie Inhalte von externen Quellen zitieren, sollten Sie blockquotes verwenden, damit klar ist, was zitiert wurde. In diesem speziellen Fall war die Formatierung schrecklich und würde eine Behandlung erfordern. Auch der Inhalt, den Sie bearbeitet haben, ist * nicht * notwendig, um die Frage zu beantworten, und es besteht keine Notwendigkeit, sie tatsächlich zu kopieren. Die Antwort ist bereits ohne sie abgeschlossen, das "warum" keine polykinded -Instanz ist vorhanden, kann in einer anderen Frage beantwortet oder einfach als Link zum * weiteren * Lesen gelassen werden. – Bakuriu

+0

Was ist der Nutzen Ihrer '==' type-Familie? Es ist normalerweise viel einfacher, mit der nativen Typgleichheit ('~') zu arbeiten, als eine boolesche Gleichheit im Typsystem zu erstellen. Am Ende des Tages müssen Sie '~' verwenden, um etwas mit dem Ergebnis von '==' zu tun, wie Sie es in 'foo' getan haben. –

+0

@BenjaminHodgson: '==' ist nicht meins. Es ist aus dem Basispaket. Es ist eine Typenfamilie, deren Ergebnis 'Bool' ist. Auf der anderen Seite hat das Ergebnis von ~ ~ eine Art 'Constraint'. So ist '==' in der booleschen Typ-Level-Berechnung verwendbar. Sie können dort nicht '~' verwenden. –