Что означает именно "функция внутри функтора"
В теории категорий функтор является гомоморфизмом между двумя категориями. В Haskell сказано, что аппликативный функтор позволяет нам применять функции "внутри функтора". Можно ли перевести эти слова "функционировать внутри функтора" обратно в математику или дать другое понимание? (Я знаю, что функтор может быть Maybe
, []
и т.д., но все еще изо всех сил, чтобы понять это понятие.)
2 ответа
Моя теория категорий совсем не сильна (я начал с программирования на Haskell и недавно пытался изучить некоторые из основ теории категорий некоторых ее концепций). Но вот что у меня есть:
В Haskell функтор - это конструктор типов, то есть он отображает общие типы в "типы в функторе".
В теории категорий функтор отображает объекты одной категории на объекты другой категории.
Применяя теорию категорий к Haskell, мы представляем, что работаем с категорией Hask, категорией типов Haskell.
Так что функторы Хаскелла не являются функторами общей теории категорий; все они отображаются из Hask в подкатегорию Hask (потому что тип f a
для какого-то функтора f
и произвольный тип a
все еще тип Хаскеля). Например, Maybe
функтор отображает объекты (типы) в Hask на категорию типов формы Maybe a
,
Функции являются первоклассными в Haskell, поэтому типы функций являются совершенно обычными типами (и являются объектами Hask), поэтому функторы также отображают типы функций на "типы функций в функторе". Таким образом, фраза "функция внутри функтора" является сокращением для значения в типе, которое является результатом применения функтора к типу функции. например Just (+1)
одно конкретное значение в типе Maybe (Int -> Int)
, который является объектом (типом), к которому относится Maybe
функтор отображает объект Int -> Int
,
Таким образом, "аппликативный функтор" - это функтор, у которого есть некоторые дополнительные правила, которых достаточно, чтобы принимать значения, являющиеся функциями типов, которые являются объектами категории "назначение" функтора, и применять эти значения к другим значениям в типах в категории назначения.,
С помощью Maybe
снова в качестве примера, если бы мы только знали, что это был функтор, который дает нам соответствие между объектами Int -> Char
а также Maybe (Int -> Char)
и между объектами Int
а также Maybe Int
и между объектами Char
а также Maybe Char
, Но пока у нас есть возможность принять значение в Int -> Char
и значение в Int
и произвести значение в Char
, Maybe
будучи функтором, мы не гарантируем, что у нас есть какая-либо возможность выполнить соответствующую операцию со значением в Maybe (Int -> Char)
и значение в Maybe Int
,
Когда мы также знаем, что это аппликативный функтор, тогда у нас есть возможность принять значение в Maybe (Int -> Char)
и значение в Maybe Int
и произвести значение в Maybe Char
и это удовлетворяет определенным свойствам при применении Int -> Char
значения для Int
ценности.
Насколько я знаю, аппликативные функторы не очень интересны с точки зрения теории категорий. Возможно, это связано с тем, что теория категорий связана с отношениями между объектами, которые соответствуют типам в Haskell, но с точки зрения программирования аппликативные функторы мотивируются отношениями между значениями в этих типах? (мы хотим, чтобы значения в "типах функций", полученные с помощью функтора, все еще могли быть применены к вычислениям).
Перевод Вернуться к математике
В замкнутой моноидальной категории существует понятие "показатель степени", которое "усваивает" соотношение морфизма. Затем вы можете оценить эти показатели. То есть у вас есть способ сказать (извините за мое мнение, в Stackru отсутствует mathjax)
eval : (a ~> b,a) -> b
а также мета-операции для каррирования и неостановки.
"Аппликативный функтор" отображает показатели "применимым" образом, F (a ~> b)
может сочетаться с F a
чтобы получить F b
, Это связано с тем, что аппликативные функторы являются моноидальными функторами, поэтому у них есть операция (в целевой категории)
f a -> f b -> f (a,b)
который, когда вы также Fmap Eval дает вам ap
из Хаскелла.
Я сомневаюсь, что это было полезно,
Хаскелл
Лучший способ понять аппликативный функтор - это посмотреть на тип
class Functor f => Applicative f where
pure :: a -> f a
<*> :: f (a -> b) -> f a -> f b
тривиальный пример
newtype Id a = Id a
instance Applicative Id where
pure a = Id a
Id f <*> Id a = Id (f $ a)
Id
также Monad
, На самом деле все Monad
с Applicative
,
pure = return
mf <*> mx = do f <- mf
x <- mx
return (f x)
более интересный пример, хотя это бесконечные последовательности
data Seq a = Seq a (Seq a)
instance Applicative Seq where
pure a = Seq a (pure a)
(Seq f fs) <*> (Seq x xs) = Seq (f x) (fs <$> xs)
Вы можете думать об этом как эквивалент zipWith $
в списках. Все Monad
с Applicative
, но я думаю, что бесконечная последовательность забавна, потому что соответствующий экземпляр монады... неочевиден (и довольно медленен). Это будет оставлено читателю в качестве упражнения (кстати, я привожу этот пример / упражнение из того, что я помню, прочитав, что, как мне кажется, свинарник написал на этом сайте).