Ein Beispiel, wie solch ein Datentyp es erlaubt, einen beliebigen Typ zu bewohnen, ist in Turner, D.A. (2004-07-28), Total Functional Programming, sect. 3.1, Seite 758 in Regel 2: Typ Rekursion muss covariant sein „
Lassen Sie uns eine aufwändigere Beispiel mit Haskell machen wir mit einem beginnen werde. "Schlecht" rekursive Datentyp
data Bad a = C (Bad a -> a)
.
und die Y combinator daraus ohne jede andere Form der Rekursion konstruieren. das bedeutet, dass ein Datentyp aufweist, so uns, jede Art von Rekursion erlaubt zu konstruieren, oder jede Art von einer unendlichen Rekursion bewohnen.
Die Y-Kombinator im untypisierten Lambda-Kalkül als
Y = λf.(λx.f (x x)) (λx.f (x x))
Der Schlüssel definiert ist, dass wir x
sich in x x
anzuwenden. In typisierten Sprachen ist dies nicht direkt möglich, weil es keinen gültigen Typ x
hätte. Aber unsere Bad
Datentyp ermöglicht diese Modulo Hinzufügen/Entfernen von den Konstruktor:
selfApp :: Bad a -> a
selfApp ([email protected](C x')) = x' x
x :: Bad a
machen, können wir den Konstruktor auszupacken und die Funktion nach innen x
selbst anwenden. Sobald wir wissen, wie Sie dies tun, dann ist es einfach, die Y Combinator zu konstruieren:
yc :: (a -> a) -> a
yc f = let fxx = C (\x -> f (selfApp x)) -- this is the λx.f (x x) part of Y
in selfApp fxx
Beachten Sie, dass weder selfApp
noch yc
rekursiv sind, gibt es keine rekursiven Aufruf einer Funktion selbst. Rekursion erscheint nur in unserem rekursiven Datentyp.
Wir können überprüfen, dass der konstruierte Kombinator tatsächlich das tut, was er sollte. Wir können eine Endlosschleife machen:
loop :: a
loop = yc id
oder berechnen die GCD lassen sagen:
gcd' :: Int -> Int -> Int
gcd' = yc gcd0
where
gcd0 :: (Int -> Int -> Int) -> (Int -> Int -> Int)
gcd0 rec a b | c == 0 = b
| otherwise = rec b c
where c = a `mod` b
Schöne Antwort. Ich mag diesen eleganten Ansatz mit seiner theoretischen Erklärung (Einbettung des untypisierten Lambda-Kalküls). Wäre es möglich, es so zu erweitern, dass es der fraglichen Sprache eine willkürliche Rekursion gibt (sagen wir Agda)? –
@ PetrPudlák Also unterhielt ich mich nur mit meinen Officemates, die weit besser Theoretiker sind als ich. Der Konsens ist, dass dieses "Schlechte" nicht zu einem Begriff vom Typ "Für immer" führen würde. a (was dir wirklich wichtig ist; Rekursion ist nur ein Mittel, um dorthin zu gelangen). Das Argument würde so gehen: Sie können ein mengentheoretisches Modell von Agda konstruieren; dann können Sie zu diesem Modell eine Interpretation von 'Bad' als eine Ein-Element-Menge hinzufügen; Da es im resultierenden Modell noch unbewohnte Typen gibt, gibt es keine Funktion, die "Bad" -Begriffe in Schleifenbegriffe eines anderen Typs umwandelt. –