Frage

Dieser Code kompiliert fein:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

instance Sel a s (b->(c,a)) where
  type Res a s (b->(c,a)) = (b -> s -> (c,s))

, aber sobald ich das R Prädikat ghc hinzufügen fehlschlägt:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

class R a where
  type Rec a :: *
  cons :: a -> Rec a
  elim :: Rec a -> a
instance Sel a s (b->(c,Rec a)) where
  type Res a s (b->(c,Rec a)) = (b -> s -> (c,s))

beschweren, dass:

    Illegal type synonym family application in instance:
        b -> (c, Rec a)
    In the instance declaration for `Sel a s (b -> (c, Rec a))'

, was es bedeutet, und (am wichtigsten), wie kann ich es beheben?

Danke

War es hilfreich?

Lösung

Typ Familien sind Einbahn: Sie Rec a seiner berechneten Typ erweitern können, aber Sie können nicht (eindeutig) gehen von der Expansion zurück zu Rec a. Dies macht Anwendungen von Typ-Funktionen zum Beispiel Signaturen nicht geeignet, da sie nie die Instanz auslösen können anzuwenden.

Sie könnten versuchen, statt:

instance Rec a ~ reca => Sel a s (b->(c,reca))

Dies bedeutet etwas anderes: sagt es jede Funktion b -> (c, reca) eine Instanz ist, und dann, wenn es unwiderruflich abgestimmt hat, den Compiler überprüft, ob Rec a ~ reca. Aber das könnte gut genug sein will in Ihrem Fall zu tun.

Andere Tipps

Rec ist kein Typkonstruktor; es ist eine Art Funktion. Vielleicht können Sie es nur in der Art eines Wertes von Typdefinition verwenden, nicht in einer Klassendeklaration? Ich vermute, wild hier; Ich habe nicht alle die Regeln für Typ Familien verstehen.

Ich weiß nicht, wie es zu beheben, aber einige Dinge zu versuchen, sind:

  • Sie sich von Klasse Sel befreien und nur type family Res a s b :: * definieren. Verwenden type instance anstelle der Klasse Mechanismus.

  • Es ist kaum möglich, dass Art machen Rec injektiv data verwendet, wird helfen, aber ich glaube nicht.

  • Cut zurück auf die kleinste Anzahl von Spracherweiterungen, könnte möglicherweise Arbeit wird es einfacher für andere, Ihnen zu helfen, und es könnte der Compiler auch helfen.

Es bedeutet, dass es nicht erlaubt ist, um Typ-synomym Familien zu verwenden, wenn Typ-Instanzen zu deklarieren. Im Abschnitt „Typ Familien und Instanzdeklarationen“ des GHC Handbuch.

Die einzige Möglichkeit, das Problem beheben kann, ist so zu umgestalten, um nicht irgendwie müssen.

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