Para empezar, tenemos la hermosa definición
x = 1 : map (2*) x
que en sí mismo es un poco alucinante si nunca lo has visto antes. De todos modos, es un truco bastante estándar de pereza y recursividad. Ahora, nos desharemos de la recursividad explícita usando fix
, y point-free-ify.
x = fix (\vs -> 1 : map (2*) vs)
x = fix ((1:) . map (2*))
Lo siguiente que vamos a hacer es expandir la :
sección y hacer map
innecesariamente complejo.
x = fix ((:) 1 . (map . (*) . (*2)) 1)
Bueno, ahora tenemos dos copias de esa constante 1
. Eso nunca funcionará, así que usaremos el aplicativo del lector para eliminarlo. Además, la composición de funciones es un poco basura, así que reemplacemos eso con (<$>)
lo que podamos.
x = fix (liftA2 (.) (:) (map . (*) . (*2)) 1)
x = fix (((.) <$> (:) <*> (map . (*) . (*2))) 1)
x = fix (((<$>) <$> (:) <*> (map <$> (*) <$> (*2))) 1)
A continuación: esa llamada a map
es demasiado legible. Pero no hay nada que temer: podemos usar las leyes de las mónadas para expandirlo un poco. En particular fmap f x = x >>= return . f
, entonces
map f x = x >>= return . f
map f x = ((:[]) <$> f) =<< x
Podemos señalar, sin ify, sustituir (.)
con (<$>)
, y luego añadir algunas secciones espurias:
map = (=<<) . ((:[]) <$>)
map = (=<<) <$> ((:[]) <$>)
map = (<$> ((:[]) <$>)) (=<<)
Sustituyendo esta ecuación en nuestro paso anterior:
x = fix (((<$>) <$> (:) <*> ((<$> ((:[]) <$>)) (=<<) <$> (*) <$> (*2))) 1)
Finalmente, rompes tu barra espaciadora y produces la maravillosa ecuación final
x=fix(((<$>)<$>(:)<*>((<$>((:[])<$>))(=<<)<$>(*)<$>(*2)))1)