Комментарии 17
Но есть нюанс: у стрелки первый аргумент s находится в негативной позиции, а у стрелки — в позитивной (что делает стрелку профунктором, а запятую бифунктором).
Вообще говоря, тут далеко не очевидно, ху из ху. А ведь это практически самое начало.
Кстати, для тех кто хочет узнать что же всё-таки имел в виду автор.
Стрелка по первому аргументу является "обратным функтором": если мы попытаемся составить для неё map
-подобную операцию, то окажется что она будет работать не в ту сторону:
-- для нормальных функторов
map :: (x -> y) -> [x] -> [y]
-- а вот что выходит для стрелки
type Arrow x = x -> Int
map :: (x -> y) -> Arrow y -> Arrow x
Вот, да. Непонятно что есть негативная/позитивная позиция.
Функторы бывают ковариантные и контровариантные. Бифункторы могут быть ковариантнтнымт по одному аргументу и контравариантными по другому. (,) ковариантен по обоим аргументам. А (->) контравариантен по первому и контравариантен по второму. И, до кучи, композиция контравариантный функторов будет ковариантна.
Кмк статья для тех кто уже знает, но, все равно, спасибо.
То есть получается, что функция (s->a) — это отображение множества (s) на множество (a) через операцию, описываемую самой фунцией (->). Другими словами, результат операции над множеством (s) выгружается в (a). А кортеж, будучи произведением (s,a) по сути является результатом совершенно конкретной (произведение) функции двух переменных без выгрузки результата. Так?
Автор, если уж вы зафиксировали первый аргумент, то почему бы вместо ((,) s)
и ((->) s)
не написать нормальные (s,)
и (s ->)
? На одну пару скобок будет меньше, что значительно упростит восприятие. А то в данный момент рисунок для инстанса Adjoint выглядит как упражнение на поиск парных скобок...
Видимо Haskell это способ создать область, куда не проникают программисты из Индии
Повесть о стрелке и запятой