Pour commencer, nous avons la belle définition
x = 1 : map (2*) x
ce qui en soi est un peu hallucinant si vous ne l'avez jamais vu auparavant. Quoi qu'il en soit, c'est un truc assez classique de paresse et de récursivité. Maintenant, nous allons nous débarrasser de la récursivité explicite en utilisant fix
, et point-free-ify.
x = fix (\vs -> 1 : map (2*) vs)
x = fix ((1:) . map (2*))
La prochaine chose que nous allons faire est d'élargir la :
section et de rendre la partie map
inutilement complexe.
x = fix ((:) 1 . (map . (*) . (*2)) 1)
Eh bien, nous avons maintenant deux copies de cette constante 1
. Cela ne fonctionnera jamais, nous utiliserons donc l'applicatif du lecteur pour dédupliquer cela. De plus, la composition des fonctions est un peu nul, alors remplaçons cela par (<$>)
là où nous le pouvons.
x = fix (liftA2 (.) (:) (map . (*) . (*2)) 1)
x = fix (((.) <$> (:) <*> (map . (*) . (*2))) 1)
x = fix (((<$>) <$> (:) <*> (map <$> (*) <$> (*2))) 1)
Ensuite: cet appel à map
est beaucoup trop lisible. Mais il n'y a rien à craindre: on peut utiliser les lois de la monade pour l'élargir un peu. En particulier fmap f x = x >>= return . f
, donc
map f x = x >>= return . f
map f x = ((:[]) <$> f) =<< x
Nous pouvons sans point-ify, remplacer (.)
par (<$>)
, puis ajouter des sections parasites:
map = (=<<) . ((:[]) <$>)
map = (=<<) <$> ((:[]) <$>)
map = (<$> ((:[]) <$>)) (=<<)
En remplaçant cette équation dans notre étape précédente:
x = fix (((<$>) <$> (:) <*> ((<$> ((:[]) <$>)) (=<<) <$> (*) <$> (*2))) 1)
Enfin, vous cassez votre barre d'espace et produisez la merveilleuse équation finale
x=fix(((<$>)<$>(:)<*>((<$>((:[])<$>))(=<<)<$>(*)<$>(*2)))1)