Per cominciare, abbiamo la bella definizione
x = 1 : map (2*) x
che di per sé è un po 'sconvolgente se non l'hai mai visto prima. Ad ogni modo è un trucco abbastanza standard di pigrizia e ricorsione. Ora, ci libereremo della ricorsione esplicita usando fix
e point-free-ify.
x = fix (\vs -> 1 : map (2*) vs)
x = fix ((1:) . map (2*))
La prossima cosa che faremo è espandere la :
sezione e rendere map
inutilmente complesso.
x = fix ((:) 1 . (map . (*) . (*2)) 1)
Bene, ora abbiamo due copie di quella costante 1
. Non funzionerà mai, quindi useremo l'applicativo del lettore per deduplicarlo. Inoltre, la composizione delle funzioni è un po 'spazzatura, quindi sostituiamola con quella (<$>)
che possiamo.
x = fix (liftA2 (.) (:) (map . (*) . (*2)) 1)
x = fix (((.) <$> (:) <*> (map . (*) . (*2))) 1)
x = fix (((<$>) <$> (:) <*> (map <$> (*) <$> (*2))) 1)
Il prossimo: quella chiamata a map
è troppo leggibile. Ma non c'è nulla da temere: possiamo usare le leggi della monade per espanderlo un po '. In particolare fmap f x = x >>= return . f
, quindi
map f x = x >>= return . f
map f x = ((:[]) <$> f) =<< x
Possiamo point-free-ify, sostituire (.)
con (<$>)
e quindi aggiungere alcune sezioni spurie:
map = (=<<) . ((:[]) <$>)
map = (=<<) <$> ((:[]) <$>)
map = (<$> ((:[]) <$>)) (=<<)
Sostituendo questa equazione nel nostro passaggio precedente:
x = fix (((<$>) <$> (:) <*> ((<$> ((:[]) <$>)) (=<<) <$> (*) <$> (*2))) 1)
Infine, rompi la barra spaziatrice e produci la meravigliosa equazione finale
x=fix(((<$>)<$>(:)<*>((<$>((:[])<$>))(=<<)<$>(*)<$>(*2)))1)