Ist es möglich, ohne zu implementieren myCycle
myCycle
oder xs
auf der rechten Seite zu erwähnen?
Die Antwort ist ja und nein (nicht unbedingt in dieser Reihenfolge).
Andere Leute haben den Fixpunktkombinator erwähnt. Wenn Sie einen Fixpunktkombinator fix :: (a -> a) -> a
haben, können Sie, wie Sie in einem Kommentar zu Pubbys Antwort schreiben, myCycle = fix . (++)
schreiben.
Aber die Standard-Definition von fix
ist dies:
fix :: (a -> a) -> a
fix f = let r = f r in r
-- or alternatively, but less efficient:
fix' f = f (fix' f)
Beachten Sie, dass die Definition von fix
beinhaltet eine linksseitige Variable auf der rechten Seite seiner Definition (r
in der ersten Definition zu erwähnen, fix'
in der zweiten). Was wir bisher wirklich gemacht haben, ist das Problem auf fix
zu schieben.
Das Interessante daran ist zu beachten, dass Haskell auf einem typisierten Lambda-Kalkül basiert, und das aus gutem technischen Grund, die meisten typisierten Lambda-Kalküle sind so ausgelegt, dass sie nicht „nativ“ den Punkt combinator fixiert auszudrücken. Diese Sprachen werden nur dann Turing-vollständig, wenn Sie ein zusätzliches Feature "on top" des Basiskalküls hinzufügen, das die Berechnung von Fixpunkten ermöglicht. Zum Beispiel wird jeder von diesen tun:
- Fügen Sie
fix
als primitive zum Kalkül.
- Hinzufügen rekursiver Datentypen (die Haskell hat; dies ist eine andere Möglichkeit,
fix
in Haskell zu definieren).
- Lassen Sie zu, dass die Definitionen sich auf die zu definierende Kennung auf der linken Seite beziehen (die Haskell ebenfalls hat).
Dies ist eine nützliche Art von Modularität aus vielen Gründen-on ist, dass ein Lambda-Kalkül ohne Fixpunkte ist auch ein Proof-System für die Logik, eine andere, dass fix
-weniger Programme in vielen solchen Systemen nachgewiesen werden kann, beenden .
EDIT: Hier fix
mit rekursiven Typen geschrieben. Nun ist die Definition von fix
selbst ist nicht rekursiv, aber die Definition des Rec
Typs ist:
-- | The 'Rec' type is an isomorphism between @Rec [email protected] and @Rec a -> [email protected]:
--
-- > In :: (Rec a -> a) -> Rec a
-- > out :: Rec a -> (Rec a -> a)
--
-- In simpler words:
--
-- 1. Haskell's type system doesn't allow a function to be applied to itself.
--
-- 2. @Rec [email protected] is the type of things that can be turned into a function that
-- takes @Rec [email protected] arguments.
--
-- 3. If you have @foo :: Rec [email protected], you can apply @[email protected] to itself by doing
-- @out foo foo :: [email protected] And if you have @bar :: Rec a -> [email protected], you can do
-- @bar (In bar)@.
--
newtype Rec a = In { out :: Rec a -> a }
-- | This version of 'fix' is just the Y combinator, but using the 'Rec'
-- type to get around Haskell's prohibition on self-application (see the
-- expression @out x [email protected], which is @[email protected] applied to itself):
fix :: (a -> a) -> a
fix f = (\x -> f (out x x)) (In (\x -> f (out x x)))
'myCycle = \ xs -> Lassen Sie ys = xs ++ ys in ys '. 'fix' inline. –