Frage

Ich habe ein Problem mit Haskells Scoping in where Definitionen. Wenn ich die folgende Funktion f habe, wo ich die x auf die lokal definierte Funktion f1 übergeben möchte, ohne explizit als Parameter zu verwenden, erhalte ich eine Fehlermeldung, dass die Art der x mit dem man in der Ausgabe von f1 unvereinbar ist, obwohl es das gleiche sein:

f :: Eq a => a -> [a]
f x = f1 x
    where
        f1 :: Eq a => a -> [a]
        f1 y = [ x, y ]

Der Fehler ist die folgende:

    Couldn't match expected type `a1' against inferred type `a'
      `a1' is a rigid type variable bound by
           the type signature for `f1' at test.hs:4:11
      `a' is a rigid type variable bound by
          the type signature for `f' at test.hs:1:8
    In the expression: x
    In the expression: [x, y]
    In the definition of `f1': f1 y = [x, y]
Failed, modules loaded: none.

Wenn ich aber die x als zusätzliche Parameter übergeben, wie ich in dem folgenden Code mit der Funktion g tat, es funktioniert gut:

g :: Eq a => a -> [a]
g x = g1 x x
    where
        g1 :: Eq a => a -> a -> [a]
        g1 x y = [ x, y ]

Gibt es eine Möglichkeit, die Art a in f kompatibel zum Typ a (oder a1) in f1 zu machen?

War es hilfreich?

Lösung

Das Problem mit Ihrem Code ist der lokal f1 Typ Signatur scoped. Es gibt an, dass f1 jede Art nehmen

f1 :: Eq a => a -> [a]

Auch wenn dies eine lokale Funktion ist, haben Sie diese Funktion verallgemeinern Lage sein, eine Art zu nehmen, die nicht innerhalb von f existieren werden, was auch immer diese Funktion von f HAS kommen empfängt, so dass die Art Unterschrift ist nicht erforderlich.

Entfernen Sie einfach den f1-Typen Signatur.

Edit: Lesen Sie meine Post zurück zu mir, es ist ein bisschen unklar. ein in f1 ist eine parametrisierte Typ, der alles, aber die an sie übergebenen Argumente sind bereits gebunden in f nehmen. So kann diese Funktion nur erhalten, was ihre Mutterfunktion empfängt, die Art Signatur Sie es gibst bricht diese Regel. Hoffe, das ist ein wenig klarer.

Andere Tipps

Dave ist rechts oben. Eine weitere Möglichkeit, daran zu denken ist, dass, obwohl beide Ihrer Art Signaturen auf die Variable a beziehen, es ist nicht wirklich die gleiche Art Variable. In der Haskell-Prime-Notation können beide Unterschriften mehr explizit geschrieben als:

forall a . Eq a => a -> [a]

was bedeutet, dass für beide Funktionen, sie ein Argument irgendwelcher Art (innerhalb Eq) annehmen kann. Dies ist offensichtlich nicht der Fall. In Standard Haskell 98, ist die einzige Option, die Art Signatur für f1 zu verzichten. Aber GHC (und andere?) Unterstützung lexikalisch scoped Variablen vom Typ . So könnten Sie schreiben

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a. Eq a => a -> [a]
f x = f1 x
    where
        f1 :: a -> [a]
        f1 y = [ x, y ]

und das würde gut funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top