Ist es möglich, eine GHC-Erweiterung zu verwenden, um eine neue Typklasse zu definieren, die zu Tupeln beliebiger Länge verallgemeinert wird?Neue Typklasse mit generischer Instanzdefinition für Tupel beliebiger Länge
Es gab bereits einige Fragen über das Verhalten von eingebauten Klassen in Prelude und Base (einige Klassen unterstützen bis zu 15-Elemente Tupel, einige bis zu 7) und über die (Nicht-) Möglichkeit, diese Klassen zu erweitern.
Präludium und Basisverhalten: Haskell Tuple Size Limit
erstreckt Show mit neuen Definitionen: Extend a Show instance to a Tuple of any size
ich eine etwas andere Frage zu stellen. Wenn ich eine völlig neue Typklasse erstelle, ist es möglich, eine Instanzregel hinzuzufügen, die Tupel beliebiger Länge behandelt (möglicherweise unter Verwendung einer GHC-Erweiterung)?
Hier ist ein Beispiel für eine solche Klasse namens PartialOrder. Ich mag Tupel beliebiger Größe ermöglichen, teilweise mit einer Definition
(a,b ... , z) <= (a1,b1, ... , z1) iff (a <= a1) && (b <= b1) && ... && (z <= z1)
Hier ist mein erster Stich mit der folgenden Regel im Vergleich zu dem traditionellen „definieren die Klasse für Tupel bis zu einer beliebigen Größe“ Ansatz.
Gibt es eine GHC-Erweiterung, die zum Schreiben von Instanzdefinitionen für Tupel beliebiger Länge verwendet werden kann?
Ich denke, ich kann Vorlage Haskell oder ein externes Programm verwenden, um Definitionen im Voraus zu generieren, aber nicht auf Abruf wie C++ - Vorlagen generieren.
-- Sets equipped with the (is_subset) operation are an example of a
-- partial order.
--
-- {} < {a} less than
-- {} = {} equal to
-- {a, b} > {b} greater than
-- {a} ~ {b} incomparable
--
-- in order to define a partial order we need a definition of (<=)
data PartialOrdering = POLessThan | POGreaterThan | POEqual | POIncomparable deriving (Eq, Show)
class PartialOrder a where
lessThanEq :: a -> a -> Bool
instance PartialOrder PartialOrdering where
lessThanEq POIncomparable _ = False
lessThanEq _ POIncomparable = False
-- with incomparables dealt with...
lessThanEq POLessThan _ = True
lessThanEq POEqual POLessThan = False
lessThanEq POEqual _ = True
lessThanEq POGreaterThan POGreaterThan = True
lessThanEq POGreaterThan _ = False
-- note this is different from the semantics for Ord applied to tuples,
-- which uses lexicographic ordering.
--
-- (a,b) is less than or equal to (c,d) iff
-- a <= b and c <= d
-- 2 element tuple
instance (PartialOrder a, PartialOrder b) => PartialOrder (a, b) where
lessThanEq (a,b) (c,d) = (lessThanEq a c) && (lessThanEq b d)
-- 3 element tuple
instance (PartialOrder a, PartialOrder b, PartialOrder c) => PartialOrder (a, b, c) where
lessThanEq (a,b,c) (d,e,f) = (lessThanEq a d) && (lessThanEq b e) && (lessThanEq c f)
-- 4 element tuple
instance (PartialOrder a, PartialOrder b, PartialOrder c, PartialOrder d) => PartialOrder (a, b, c, d) where
lessThanEq (a,b,c,d) (e,f,g,h) = (lessThanEq a e) && (lessThanEq b f) && (lessThanEq c g) && (lessThanEq d h)
-- etc.
main = putStrLn "hi"
nur ein Vorschlag : Warum Sie nicht über eine Länge indizierte Liste verwenden? Solche Datentypen sind isomorph zu Tupeln. Es ist einfach, es mit GADTs zu definieren. –