Notez que la solution triviale n'est pas très efficace, en raison de la croissance quadratique de la complexité. Si vous avez essayé d'utiliser la pliose habituelle pour replier la conversion (aveuglément), mais ma tentative p> n'a pas fonctionné comme on m'y attendait. P> P>
5 Réponses :
Essayez ceci:
reverse = foldl' (flip (:)) []
Chris: Disons simplement: l'accumulateur a de type [A] -> [a]. Il s'agit essentiellement de créer beaucoup de lambdas encapsulés, qui ajoutent les éléments de la liste à l'avant de ce qui est passé - [].
@Chris je le préfère personnellement dans la notation ponctuelle, il est plus lisible (pour moi) de cette façon: inverse xs = pli-pli f id xs [] où f x r = r. (x:) code>. Ainsi, lorsque le résultat de pliose f id xs code> est enfin appliqué sur [] code>, le f x1 r1 code> est appelé, qui produit r1 . (x1 :) $ [] code> à quel point r1 code> est forcé. À la fin de la chaîne entière ID. (Xn :). .... (x2 :) (x1:) code> est appliqué à [] code>. Cela utilise la méthode standard HASKELL de codage de la différence ouverte (AKA "DIFFERENCE -" I>) comme chaînes de fonctions de production de liste, :: [a] -> [a] code>. Idem est utilisé dans data.S. / code> je crois.
C'est l'un de ces cas rares où replier ' code> est pas i> mieux. L'action d'appliquer aveuglément un constructeur paresseux n'est jamais retardée car il n'y a jamais d'avantage à le faire. Dans le cas où le code produit est réellement différent, il ne peut s'agir que de pire.
Considérez les éléments suivants:
reverse' xs = (appEndo . foldr (flip mappend . Endo . (:)) mempty $ xs) [] reverse' xs = (foldr (flip (.) . (:)) id $ xs) [] reverse' = flip (foldr (flip (.) . (:)) id) []
foldl (\acc x -> x:acc) [] [1,2,3]
Mauvais endroit pour répondre, mais ce que je cherchais.
Je tiens à dire que je me suis rendu compte que ma réponse n'était pas correcte il y a très longtemps, mais à mon étonnement, de nombreuses personnes ont déjà voté (au total, j'ai eu 5 voix contre 5 votes). Je pense parfois que les gens atterrissent à cette page lorsque vous recherchez exactement cette réponse, j'ai donc décidé de le garder ici car à la fin, il s'agit d'aider les autres à trouver des réponses qu'ils recherchent.
Fondamentalement, vous devez transformer 1: 2: 3: [] dans (3 :) (2 :) (1 :) et l'appliquer à []. Ainsi:
reverse' xs = foldr (\x g -> g.(x:)) id xs []
Une ancienne question, je sais, mais existe-t-il quelque chose de non-optimal sur cette approche, il semble que la pliose serait plus rapide en raison de l'évaluation paresseuse et du code est assez concis:
reverse' :: [a] -> [a] reverse' = foldr (\x acc -> acc ++ [x]) []
Cette mise en œuvre est O (n ^ 2) sur la longueur de la liste. À chaque étape, le courant ACC code> devient des ordures et une nouvelle liste est créée avec x code> comme dernier élément. L'évaluation paresseuse ne change que quand i> cela se produit. Dans une langue stricte, cela se produirait avant inverse ' code> retour. Dans HASKELL, il se produira lorsque vous forcez la liste des résultats.
Ah, ça fait un sens parfait. N'a pas réfléchi au fait que cela créerait une nouvelle liste à chaque itération. Merci!
Certaines applications ++ CODE> STATICITIMENT-DISPONIBLES peuvent apparaître dans le lavage, mais ici ils se produiront tous et vous paierez beaucoup pour eux.