Я пришел к этому сообщению, чтобы лучше понять вывод печально известной цитаты из статьи Мак Лейна Теория категорий для рабочего математика.
При описании того, что что-то есть, часто одинаково полезно описать то, чем это не является.
Тот факт, что Мак Лейн использует это описание для описания монады, может означать, что оно описывает нечто уникальное для монад. Потерпите меня. Чтобы развить более широкое понимание этого утверждения, я считаю, что необходимо прояснить, что он не описывает что-то уникальное для монад; это утверждение в равной степени описывает, среди прочего, Applicative и Arrows. По той же причине у нас может быть два моноида на Int (Sum и Product), у нас может быть несколько моноидов на X в категории эндофункторов. Но это еще не все сходство.
И Monad, и Applicative соответствуют критериям:
The statement uses "Category of..." This defines the scope of the statement. As an example, the Functor Category describes the scope of f * -> g *
, i.e., Any functor -> Any functor
, e.g., Tree * -> List *
or Tree * -> Tree *
.
What a Categorical statement does not specify describes where anything and everything is permitted.
In this case, inside the functors, * -> *
aka a -> b
is not specified which means Anything -> Anything including Anything else
. As my imagination jumps to Int -> String, it also includes Integer -> Maybe Int
, or even Maybe Double -> Either String Int
where a :: Maybe Double; b :: Either String Int
.
Итак, утверждение сводится к следующему:
- область действия функтора
:: f a -> g b
(т. е. от любого параметризованного типа к любому параметризованному типу)
- endo + functor
:: f a -> f b
(т.е. любой параметризованный тип к одному и тому же параметризованному типу) ... иначе говоря,
- моноид в категории эндофунктора
Итак, в чем же сила этой конструкции? Чтобы оценить всю динамику, мне нужно было увидеть, что типичные рисунки моноида (одиночный объект с тем, что выглядит как стрелка идентичности, :: single object -> single object
), не иллюстрируют, что мне разрешено использовать стрелку, параметризованную с помощью любого числа. значений моноида из объекта типа один, разрешенного в Monoid. Определение эквивалентности endo, ~ identity стрелка игнорирует значение типа функтора, а также тип и значение самого внутреннего, "полезного" уровня. Таким образом, эквивалентность возвращает true
в любой ситуации, когда совпадают функциональные типы (например, Nothing -> Just * -> Nothing
эквивалентно Just * -> Just * -> Just *
, потому что они оба Maybe -> Maybe -> Maybe
).
Sidebar: ~ outside is conceptual, but is the left most symbol in f a
. It also describes what "Haskell" reads-in first (big picture); so Type is "outside" in relation to a Type Value. The relationship between layers (a chain of references) in programming is not easy to relate in Category. The Category of Set is used to describe Types (Int, Strings, Maybe Int etc.) which includes the Category of Functor (parameterized Types). The reference chain: Functor Type, Functor values (elements of that Functor's set, e.g., Nothing, Just), and in turn, everything else each functor value points to. In Category the relationship is described differently, e.g., return :: a -> m a
is considered a natural transformation from one Functor to another Functor, different from anything mentioned thus far.
Возвращаясь к основному потоку, в целом, для любого определенного тензорного произведения и нейтрального значения утверждение заканчивается описанием удивительно мощной вычислительной конструкции, порожденной ее парадоксальной структурой:
- снаружи он выглядит как единый объект (например,
:: List
); статический
- but inside, permits a lot of dynamics
- any number of values of the same type (e.g., Empty | ~NonEmpty) as fodder to functions of any arity. The tensor product will reduce any number of inputs to a single value... for the external layer (~
fold
that says nothing about the payload)
- бесконечный диапазон и типа и значений для самого внутреннего слоя
В Haskell важно уточнить применимость оператора. Мощность и универсальность этой конструкции не имеет абсолютно ничего общего с монадой как таковой. Другими словами, конструкция не зависит от того, что делает монаду уникальной.
Когда вы пытаетесь понять, нужно ли создавать код с общим контекстом для поддержки вычислений, которые зависят друг от друга, или вычислений, которые могут выполняться параллельно, это печально известное утверждение, со всем его описанием, не является контрастом между выбором Аппликатив, стрелки и монады, а скорее описание того, насколько они одинаковы. Для рассматриваемого решения утверждение спорно.
Это часто понимают неправильно. Далее в заявлении join :: m (m a) -> m a
описывается как тензорное произведение моноидального эндофунктора. Однако он не формулирует, как в контексте этого утверждения также мог быть выбран (<*>)
. Это действительно пример шести / полдюжины. Логика объединения значений абсолютно одинакова; один и тот же ввод генерирует одинаковый вывод для каждого (в отличие от моноидов Sum и Product для Int, потому что они генерируют разные результаты при объединении Ints).
Итак, резюмируем: моноид в категории эндофункторов описывает:
~t :: m * -> m * -> m *
and a neutral value for m *
(<*>)
и (>>=)
оба обеспечивают одновременный доступ к двум значениям m
для вычисления единственного возвращаемого значения. Логика, используемая для вычисления возвращаемого значения, точно такая же. Если бы не разные формы параметризируемых ими функций (f :: a -> b
по сравнению с k :: a -> m b
) и положение параметра с одинаковым типом возвращаемого значения вычисления (т.е. a -> b -> b
по сравнению с b -> a -> b
для каждого соответственно), я подозреваю, что мы могли бы параметризовать моноидальная логика, тензорное произведение, для повторного использования в обоих определениях. В качестве упражнения, чтобы понять суть, попробуйте реализовать ~t
, и вы получите (<*>)
и (>>=)
в зависимости от того, как вы решите определить его forall a b
.
Если мой последний пункт как минимум концептуально верен, тогда он объясняет точную и единственную вычислительную разницу между Applicative и Monad: функции, которые они параметризуют. Другими словами, разница внешняя по отношению к реализации этих классов типов.
В заключение, по моему собственному опыту, печально известная цитата Мак Лейна предоставила мне отличный мем «goto», ориентир, на который я мог ссылаться при навигации по категориям, чтобы лучше понять идиомы, используемые в Haskell. Ему удается охватить объем мощных вычислительных мощностей, которые прекрасно доступны в Haskell.
Однако есть ирония в том, что я сначала неправильно понял применимость утверждения вне монады и то, что, надеюсь, передал здесь. Все, что он описывает, оказывается похожим между Applicative и Monads (и Arrows среди других). Но в нем не говорится о небольшом, но полезном различии между ними.
- E
person
Edmund's Echo
schedule
20.04.2018