пользователь user11228628 привел меня к пониманию.Вот несколько идей, которые я получил во время чтения, и некоторые пошаговые преобразования.
Insights
- Продолжения не отменяются напрямую.Они в конечном итоге могут быть отменены (путем бета-сокращения), потому что их можно выделить.
- Шаблон, который вы ищете для этого преобразования, -
\k c -> k (c . f)
(или, если вы любите нечитабельные, бессмысленные, (. (. f))
) для любого f
(обратите внимание, что f
не является параметром для лямбды). - Как duplode указывает в комментарии , функции стиля продолжения передачиможет рассматриваться как функтор, и
obfuscate
является их определением fmap
. - Хитрость извлечения функции, подобной этой, из
foldr
работает для любой функции, которая может быть допустимой fmap
.
Полное преобразование из первого блока кода во второй
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (\((y:ys),r) -> c (ys,(x,y):r))
Извлечение c
из лямбды
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (c . \((y:ys),r) -> (ys,(x,y):r))
Замена obfuscate
для его определения
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x = obfuscate (\((y:ys),r) -> (ys,(x,y):r))
Извлечение obfuscate
из лямбды
zipRev xs ys = foldr f id xs snd (ys,[])
where
f = obfuscate . \x ((y:ys),r) -> (ys,(x,y):r)
Извлечение obfuscate
из f
zipRev xs ys = foldr (obfuscate . f) id xs snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Сobfuscate
следует законам Функтора, мы можем вытащить его из foldr
zipRev xs ys = obfuscate (flip (foldr f) xs) id snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Inline obfuscate
zipRev xs ys = (\k c -> k (c . flip (foldr f) xs)) id snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Бета-уменьшение
zipRev xs ys = (id (snd . flip (foldr f) xs)) (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Упрощение
zipRev xs ys = snd (foldr f (ys,[]) xs)
where
f x (y:ys,r) = (ys,(x,y):r)
Обоснование для функций вытягивания, которые действительны fmap
с из foldr
foldr (fmap . f) z [x1,x2,...,xn]
Расширение foldr
(fmap . f) x1 . (fmap . f) x2 . ... . (fmap . f) xn $ z
Встроенный внутренний .
s
fmap (f x1) . fmap (f x2) . ... . fmap (f xn) $ z
Применение законов Функтора
fmap (f x1 . f x2 . ... . f xn) $ z
Этап-расширениераздел в скобках
fmap (\z2 -> f x1 . f x2 . ... . f xn $ z2) z
Напишите лямбда-тело в терминах foldr
fmap (\z2 -> foldr f z2 [x1,x2,...,xn]) z
Напишите лямбда-тело в терминах flip
fmap (flip (foldr f) [x1,x2,...,xn]) z
Бонус: Обоснование для функций вытягивания, которые действительны contramap
с из foldr
foldr (contramap . f) z [x1,x2,...,xn]
Расширение foldr
(contramap . f) x1 . (contramap . f) x2 . ... . (contramap . f) xn $ z
Встроенный внутренний .
s
contramap (f x1) . contramap (f x2) . ... . contramap (f xn) $ z
Применение контравариантных законов
contramap (f xn . ... . f x2 . f x1) $ z
Этап - разверните раздел в скобках
contramap (\z2 -> f xn . ... . f x2 . f x1 $ z2) z
Напишите лямбда-тело в терминах foldr
contramap (\z2 -> foldr f z2 [xn,...,x2,x1]) z
Напишите лямбда-тело в виде flip
contramap (flip (foldr f) [xn,...,x2,x1]) z
Применить foldr f z (reverse xs)
= foldl (flip f) z xs
contramap (flip (foldl (flip f)) [x1,x2,...,xn]) z