Frage

So habe ich ein Paar typeclasses, dass ich viel zusammen verwenden, und ich mag beide jedes Mal der Angabe zu vermeiden. Grundsätzlich anstatt,

:: (Ord a, Fractional a, Ord b, Fractional b, ... Ord z, Fractional z) =>

am Anfang aller meiner Art Spezifikationen, würde ich eher setzen

:: (OrdFractional a, OrdFractional b, ... OrdFractional z)

Also, meine erste Idee, wie dies zu tun, war nur eine neue typeclass erklärt

module Example where

class (Fractional a, Ord a) => OrdFractional a

example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool
example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

Aber das funktionierte nicht wie automagically wie ich wünschte, es wäre:

% ghci
Prelude> :l Example.hs
Ok, modules loaded: Example.
Prelude Example> example (1::Float,3::Float) (2,2) (3,1)

<interactive>:1:0:
    No instance for (OrdFractional Float)
      arising from a use of `example' at <interactive>:1:0-39
    Possible fix:
      add an instance declaration for (OrdFractional Float)
    In the expression: example (1 :: Float, 3 :: Float) (2, 2) (3, 1)
    In the definition of `it':
        it = example (1 :: Float, 3 :: Float) (2, 2) (3, 1)

Manuelles Erstellen von Instanzen scheint wie eine Drag so, als nächste, ich dachte, ich könnte versuchen, automatisch Instanzen zu erstellen:

module Example where

class OrdFractional a
instance (Fractional a, Ord a) => OrdFractional a

example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool
example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

Aber der Compiler nicht wie, dass:

ghc -c Example.hs

Example.hs:4:0:
    Illegal instance declaration for `OrdFractional a'
        (All instance types must be of the form (T a1 ... an)
         where a1 ... an are type *variables*,
         and each type variable appears at most once in the instance head.
         Use -XFlexibleInstances if you want to disable this.)
    In the instance declaration for `OrdFractional a'

So ist es eine Möglichkeit, dies zu tun?

War es hilfreich?

Lösung

Mit der ConstraintKinds Erweiterung in GHC eingeführt 7.4, Einschränkungen sind jetzt Art von Art Constraint, so dass Sie gewöhnliche Art Synonyme verwenden können, bekommen, was Sie wollen:

{-# LANGUAGE ConstraintKinds #-}

type OrdFractional a = (Ord a, Fractional a)

Andere Tipps

Was Sie wollen, ist ein Klasse-Alias. Es gibt einen Vorschlag, es zu Haskell hinzufügen unter http://repetae.net/recent/out/classalias .html

Wenn der Compiler sagt "Use -XFlexibleInstances", sollten Sie versuchen, das Hinzufügen

{-# LANGUAGE FlexibleInstances #-}

an der Spitze Ihrer Quelle (und gehen Sie die Dokumentation lesen zu lernen, was es tut, natürlich!).

In diesem speziellen Fall, dies wird Ihren Code funktioniert:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

Flexible Instanzen sind erforderlich, um den => Kontext auf der Instanz Kopf zu ermöglichen, und unentscheidbar Instanzen erforderlich sind, weil der Compiler, wenn ein OrdFractional a Kontextes Handhabung enden kann Fractional a und Ord a auf den Kontext Zugabe - die nicht direkt Hilfe bei der schließlich a zu bestimmen und unter geeignet schrecklichen Umständen kann Typprüfung abweichen; der Compiler wirklich mag das nicht. (Sie wahrscheinlich würde es nicht mögen, wenn der Compiler für immer ging oder lief aus der Erinnerung, auch nicht.)

Nein.

Ihre Lösung einer übergeordneten Klasse die anderen Klassen impliziert ist in der Nähe zu dem, was Sie wollen, das ist möglich in Haskell. Auch wenn die manuellen Instanzen dieser neuen Klasse erfordert, wird es manchmal verwendet, zum Beispiel in dem Umschreiben Bibliothek.

Wie CesarB erwähnt Klasse Aliase tun, was Sie wollen (und mehr), aber sie sind nur einen Vorschlag, der nun schon seit Jahren ist und nie umgesetzt worden ist, wahrscheinlich, weil es zahlreiche Probleme mit sich. Stattdessen haben verschiedene andere Vorschläge aufgetaucht, aber keiner von denen, wurden entweder umgesetzt. (Eine Liste dieser Vorschläge finden Sie in diesem Haskellwiki .) Eines der Projekte unter HAC5 war die GHC zu ändern, um eine kleine Teilmenge der Klasse Aliase sind genannt Kontext Synonyme ( die genau das tun, was Sie mehr für hier und nichts fragen), aber leider war es nie fertig.

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