Идея заключается в том, что значение алгебраического типа данных в Haskell имеет вид
C x_1 x_2 ... x_n
где C
является конструктором и x_i
являются аргументы. Что
gfoldl app con
делает, чтобы превратить такое значение в
con C `app` x_1 `app` x_2 ... `app` x_n
тем самым превращая a
в c a
. Давайте предположим, что тип C
является
C :: T_1 -> T_2 -> ... -> T_n -> D
тогда давайте рассмотрим типы промежуточных выражений:
con C :: c (T_1 -> T_2 -> ... -> T_n -> D)
con C `app` x_1 :: c (T_2 -> ... -> T_n -> D)
con C `app` x_1 `app` x_2 :: c (... -> T_n -> D)
con C `app` x_1 `app` x_2 ... `app` x_n :: c D
Параметрирование через c
позволяет все эти промежуточные типы быть различны. Если бы мы использовали простую складку, такую как gfoldl'
, тогда все эти промежуточные типы должны были бы быть одинаковыми.
Мотивация gfoldl
это быть одного обобщения, которое позволяет выразить функции НСБА gmapQ
и gmapT
(и некоторые другие). Типы gmapQ
и gmapT
являются:
gmapQ :: Data a => (forall d. Data d => d -> u) -> a -> [u]
gmapT :: Data a => (forall b. Data b => b -> b) -> a -> a
Хотя gmapQ
разрушается в a
в единый список u
с и может быть выражены с помощью gfoldl'
, это не было бы возможным gmapT
.
Однако, с gfoldl
, мы можем использовать c = Identity
, чтобы мы могли получить что-то вроде gmapT
и c = Const
, чтобы получить что-то вроде gmapQ
.
Для получения более подробной информации, вы также можете посмотреть на бумаге Scrap your boilerplate Reloaded, который показывает, что gfoldl
обыкновенный (еще высший порядок) складка из типа данных, который называется Spine
в этой работе.
Использование идентичности и постоянных функторы, чтобы получить как преобразование и поведения обновления от одного базового представления имеют некоторое сходство с , как вы получите операции линзы из линз «Ван Laarhoven».
«параметризация над' c' позволяет всем этим промежуточным типам быть разными »- не могли бы вы уточнить? Это не имеет особого смысла. – leftaroundabout
@leftaroundabout В 'gfoldl'' все' c X' вхождения 'r', т. Е. Все они должны быть одного типа. С 'c X' я все еще могу быть одним и тем же типом, например, в' Const r X', который изоморфен 'r'. Но я могу также заставить их всех отличаться, например, в «Identity X», который изоморфен «X». – kosmikus