Ja, wenn auch nicht in Haskell. Aber je höher Ordnung polymorphe Lambda-Kalkül (auch bekannt als System F-Omega) ist allgemeiner:
bi : forall m n a b. (forall a. m a -> n a) -> m a -> m b -> (n a, n b)
bi {m} {n} {a} {b} f x y = (f {a} x, f {b} y)
x1 : (Integer, Char)
x1 = bi {\a. List a} {\a. a} {Integer} {Char} head [2,3] "45"
x2 : (Integer, Char)
x2 = bi {\a . exists b. (a, b)} {\a. a} {Integer} {Char} (\{a}. \p. unpack<b,x>=p in fst {a} {b} x) (pack<Char, (2,'3')>) (pack<Integer, ('4',5)>)
x3 : (Integer, Double)
x3 = bi {\a. a} {\a. a} {Integer} {Double} (1+) 2 3.45
Hier schreibe ich f {T}
für explizite Art Anwendung und übernehmen jeweils eine Bibliothek eingegeben haben. Etwas wie \a. a
ist ein Lambda auf Typpegel. Das x2
Beispiel ist komplizierter, weil es auch existentielle Typen benötigt, um das andere Bit des Polymorphismus in den Argumenten lokal zu "vergessen".
Sie können dies tatsächlich simulieren in Haskell einen newtype
oder Datentyp für jedes unterschiedliche m
durch die Definition oder n
Sie instanziiert mit und entsprechend eingewickelt Funktionen f
übergeben, die hinzufügen und Konstrukteuren entsprechend entfernen. Aber das macht natürlich keinen Spaß.
bearbeiten: Ich sollte, dass dies immer noch darauf hinweisen, ist kein voll allgemeine Lösung. Zum Beispiel kann ich nicht sehen, wie Sie selbst in System F-Omega
eingeben können.Das Problem ist, dass die swap
Funktion polymorpher ist als bi
ermöglicht, und im Gegensatz zu x2
, wird die andere polymorphe Dimension nicht im Ergebnis vergessen, so dass der existenzielle Trick nicht funktioniert. Es scheint, dass Sie einen guten Polymorphismus benötigen würden, um diesen zuzulassen (so dass das Argument zu bi
über eine variierende Anzahl von Typen polymorph sein kann).
Ich glaube nicht. Sie müssten es über alle Eingabetypen quantifizieren, was eine Zusammenfassung über Einschränkungen der Typklasse erfordert. –
@LouisWasserman, gibt es einige neue Sachen (ConstraintKinds), die es erlauben, über Einschränkungen zu abstrahieren. – aemxdp
Okay, ich sehe das, aber ich glaube nicht, dass Sie die Ergebnistypen quantifizieren können, so wie Sie es müssten. Wenn es die Form 'a -> a' hätte, könnten Sie 'bi :: (cxt a, cxt b) => (für alle x. Cxt x => x -> x) -> a -> b -> (a, b) ', aber ich glaube nicht, dass Sie automatisch die" type function "von jedem Eingang zu seinem Ergebnistyp bekommen können. –