Angenommen, ich möchte die endlichen Modelle der Sprache erster Ordnung mit der Konstante c, unäre Funktion Symbol f und Prädikat P darstellen. Ich kann den Träger als Liste m
, die Konstante als ein Element von m
, die Funktion als darstellen eine Liste von geordneten Paaren von Elementen der m
(die über eine Hilfsfunktion ap
angewendet werden kann), und das Prädikat als eine Liste der Elemente der m
die es erfüllen:Wie kann ich dieses abhängig typisierte Beispiel in Haskell codieren?
-- Models (m, c, f, p) with element type a
type Model a = ([a], a, [(a,a)], [a])
-- helper function application, assumes function is total
ap :: Eq a => [(a,b)] -> a -> b
ap ((x',y'):ps) x = if x == x' then y' else ap ps x
I kann dann bestimmte Modelle bauen und Operationen an Modellen. Die Details sind nicht wichtig für meine Frage, nur die Typen (aber ich habe die Definitionen enthalten, damit Sie sehen können, wo die Typeinschränkungen kommen aus):
unitModel :: Model()
unitModel = ([()],(), [((),())], [])
cyclicModel :: Int -> Model Int
cyclicModel n | n > 0 = ([0..n-1], 0, [(i, (i+1)`mod`n) | i<-[0..n-1]], [0])
-- cartesian product of models
productModel :: (Eq a, Eq b) => Model a -> Model b -> Model (a,b)
productModel (m1, c1, f1, p1) (m2, c2, f2, p2) = (m12, c12, f12, p12) where
m12 = [(x1,x2) | x1 <- m1, x2 <- m2]
c12 = (c1, c2)
f12 = [(x12, (ap f1 (fst x12), ap f2 (snd x12))) | x12 <- m12]
p12 = [x12 | x12 <- m12, elem (fst x12) p1 && elem (snd x12) p2]
-- powerset of model (using operations from Data.List)
powerModel :: (Eq a, Ord a) => Model a -> Model [a]
powerModel (m, c, f, p) = (ms, cs, fs, ps) where
ms = subsequences (sort m) -- all subsets are "normalized"
cs = [c]
fs = [(xs, nub (sort (map (ap f) xs))) | xs <- ms] -- "renormalize" the image of f
ps = [xs | xs <- ms, elem c xs]
Nun, ich möchte Namen geben, um alle diese Modelle:
data ModelName = UnitModel
| CyclicModel Int
| Product ModelName ModelName
| Power ModelName
deriving (Show, Eq)
Schließlich möchte ich diesen Code schreiben, jeden Namen Zuordnung zum Modell es Namen:
model_of UnitModel = unitModel
model_of (CycleModel n) = cycleModel n
model_of (Product m1 m2) = productModel (model_of m1) (model_of m2)
model_of (Power m1) = powerModel (model_of m1)
ich eine Reihe von Ansätzen zu machen dies zu arbeiten versucht haben, in der Sinn der Definition von ty pes, so dass ich genau diese Definition von model_of verwenden kann, einschließlich der Verwendung von Phantom-Typen, GADTs und Typfamilien - habe aber keinen Weg gefunden, dies zu tun. (Aber andererseits bin ich ein relativer Neuling in Haskell.) Kann es getan werden? Wie soll ich das machen?
Haben Sie gerade in meine Emacs gehackt Coz ich die gleiche Antwort bereit :) – Ankur
Einer der Ansätze versucht hatte, ich war ähnlich wie diese aber nicht über die Art Einschränkungen in der Konstruktortypen, so dass ein Thema für mich aufräumt - danke. Aber ein Grund, warum ich nach anderen Ansätzen suchte, war das Gefühl, dass eine Definition wie diese zu viele Informationen über einen bestimmten Verwendungszweck enthält: Ich möchte vielleicht auch Code schreiben, der nur mit den Namen arbeitet, wo die zusätzlichen Informationen liegen Überflüssig, sagen wir einen Isomorphietest 'ModelName -> ModelName -> Bool'.Gibt es eine Möglichkeit, die ursprüngliche ModelName-Definition für diese Zwecke beizubehalten, aber model_of weiterhin zuzulassen? – lambdacalculator
Daten ErasedModel = forall t. ErasedModel (ModelName t) - würde es aber nicht empfehlen :-) – sclv