Для початку ми маємо прекрасне визначення
x = 1 : map (2*) x
що саме по собі трохи збиває з розуму, якщо ви ніколи раніше цього не бачили. У будь-якому випадку це досить стандартний трюк ліні та рекурсії. Тепер ми позбудемося явної рекурсії за допомогою fix
і point-free-ify.
x = fix (\vs -> 1 : map (2*) vs)
x = fix ((1:) . map (2*))
Наступне, що ми збираємося зробити, це розширити :
розділ і зробити map
надмірно складним.
x = fix ((:) 1 . (map . (*) . (*2)) 1)
Ну, тепер у нас є дві копії цієї константи 1
. Це ніколи не допоможе, тому ми використаємо програму читання, щоб видалити її. Крім того, склад функцій - це трохи сміття, тому давайте замінимо його на те, (<$>)
де ми можемо.
x = fix (liftA2 (.) (:) (map . (*) . (*2)) 1)
x = fix (((.) <$> (:) <*> (map . (*) . (*2))) 1)
x = fix (((<$>) <$> (:) <*> (map <$> (*) <$> (*2))) 1)
Далі: цей дзвінок map
занадто читабельний. Але боятися нічого: ми можемо використовувати закони монади, щоб трохи розширити їх. Зокрема fmap f x = x >>= return . f
, так
map f x = x >>= return . f
map f x = ((:[]) <$> f) =<< x
Ми можемо вказати ify-free, замінити (.)
на (<$>)
, а потім додати кілька помилкових розділів:
map = (=<<) . ((:[]) <$>)
map = (=<<) <$> ((:[]) <$>)
map = (<$> ((:[]) <$>)) (=<<)
Підставивши це рівняння на нашому попередньому кроці:
x = fix (((<$>) <$> (:) <*> ((<$> ((:[]) <$>)) (=<<) <$> (*) <$> (*2))) 1)
Нарешті, ви розбиваєте пробіл і створюєте чудове остаточне рівняння
x=fix(((<$>)<$>(:)<*>((<$>((:[])<$>))(=<<)<$>(*)<$>(*2)))1)