Я видел несколько вариантов использования для полиморфизма 2-го ранга (наиболее ярким примером является ST monad), но для более высокий ранг. Кто-нибудь знает о таком прецеденте?
Использовать случай для 3-го (или выше) полиморфизма?
Ответ 1
Я могу помочь, хотя такой зверь неизбежно вовлечен. Здесь шаблон, который я иногда использую при разработке синтаксиса с привязкой к привязке и индексированию Bruijn, разливается в бутылки.
mkRenSub ::
forall v t x y. -- variables represented by v, terms by t
(forall x. v x -> t x) -> -- how to embed variables into terms
(forall x. v x -> v (Maybe x)) -> -- how to shift variables
(forall i x y. -- for thingies, i, how to traverse terms...
(forall z. v z -> i z) -> -- how to make a thingy from a variable
(forall z. i z -> t z) -> -- how to make a term from a thingy
(forall z. i z -> i (Maybe z)) -> -- how to weaken a thingy
(v x -> i y) -> -- ...turning variables into thingies
t x -> t y) -> -- wherever they appear
((v x -> v y) -> t x -> t y, (v x -> t y) -> t x -> t y)
-- acquire renaming and substitution
mkRenSub var weak mangle = (ren, sub) where
ren = mangle id var weak -- take thingies to be vars to get renaming
sub = mangle var id (ren weak) -- take thingies to be terms to get substitution
Как правило, я бы использовал классы типов, чтобы скрыть наихудший из всех, но если вы распакуете словари, это то, что вы найдете.
Дело в том, что mangle
- это операция ранга-2, которая берет понятие thingy, снабженное подходящими операциями, полиморфными в наборах переменных, над которыми они работают: операции, которые сопоставляют переменные с предметами, превращаются в термина-трансформаторы. Все это показывает, как использовать mangle
для генерации как переименования, так и замены.
Вот конкретный пример этого шаблона:
data Id x = Id x
data Tm x
= Var (Id x)
| App (Tm x) (Tm x)
| Lam (Tm (Maybe x))
tmMangle :: forall i x y.
(forall z. Id z -> i z) ->
(forall z. i z -> Tm z) ->
(forall z. i z -> i (Maybe z)) ->
(Id x -> i y) -> Tm x -> Tm y
tmMangle v t w f (Var i) = t (f i)
tmMangle v t w f (App m n) = App (tmMangle v t w f m) (tmMangle v t w f n)
tmMangle v t w f (Lam m) = Lam (tmMangle v t w g m) where
g (Id Nothing) = v (Id Nothing)
g (Id (Just x)) = w (f (Id x))
subst :: (Id x -> Tm y) -> Tm x -> Tm y
subst = snd (mkRenSub Var (\ (Id x) -> Id (Just x)) tmMangle)
Мы реализуем термин обход только один раз, но в очень общем виде, тогда мы получаем подстановку, развертывая шаблон mkRenSub (который использует общий обход двумя разными способами).
В другом примере рассмотрим полиморфные операции между операторами типа
type (f :-> g) = forall x. f x -> g x
An IMonad
(индексированная монада) - это некоторая m :: (* -> *) -> * -> *
, снабженная полиморфными операторами
ireturn :: forall p. p :-> m p
iextend :: forall p q. (p :-> m q) -> m p :-> m q
так что эти операции - это ранг 2.
Теперь любая операция, параметризованная произвольной индексированной монадой, равна ранга 3. Так, например, построив обычную монадическую композицию,
compose :: forall m p q r. IMonad m => (q :-> m r) -> (p :-> m q) -> p :-> m r
compose qr pq = iextend qr . pq
полагается на количественную оценку ранга 3, как только вы распакуете определение IMonad
.
Мораль истории: как только вы занимаетесь программированием более высокого порядка над полиморфными/проиндексированными понятиями, ваши словари полезного набора становятся рангами 2, а ваши общие программы становятся рангами 3. Это, конечно, эскалация, которая может повториться снова.
Ответ 2
Возможно, лучший конец абстрактного текста, который я еще прочитал: Множественный набор требует только полиморфизма 3-го уровня в дополнение к механизму нормального типа класса Haskell.. (О, только полиморфизм 3-го ранга, неважно!)