Какой тип морфизма является «фильтром» в теории категорий? - PullRequest
0 голосов
/ 30 мая 2018

В теории категорий, считается ли операция filter морфизмом?Если да, то что это за морфизм?Пример (в Scala)

val myNums: Seq[Int] = Seq(-1, 3, -4, 2)

myNums.filter(_ > 0)
// Seq[Int] = List(3, 2) // result = subset, same type

myNums.filter(_ > -99)
// Seq[Int] = List(-1, 3, -4, 2) // result = identical than original

myNums.filter(_ > 99)
// Seq[Int] = List() // result = empty, same type

Ответы [ 4 ]

0 голосов
/ 03 июня 2018

Чтобы ответить на такой вопрос, я хотел бы сначала понять, что такое сущность фильтрации.

Например, имеет ли значение, что вход является списком?Не могли бы вы отфильтровать дерево?Я не понимаю, почему нет!Вы применили бы предикат к каждому узлу дерева и отбросили те, которые не прошли тест.

Но какова будет форма результата?Удаление узла не всегда определяется или является неоднозначным.Вы можете вернуть список.Но почему список?Любая структура данных, которая поддерживает добавление, будет работать.Вам также нужен пустой член вашей структуры данных, чтобы начать процесс добавления.Так подойдет любая унитальная магма.Если вы настаиваете на ассоциативности, вы получаете моноид.Оглядываясь назад на определение filter, мы получаем список, который действительно является моноидом.Так что мы на правильном пути.

Итак, filter - это особый случай того, что называется Foldable: структура данных, которую можно сложить, накапливая результаты в моноиде.В частности, вы можете использовать предикат для вывода одноэлементного списка, если это правда;или пустой список (элемент идентичности), если он ложный.

Если вы хотите категоричный ответ, то сгиб - это пример катаморфизма, пример морфизма в категории алгебр.(Рекурсивная) структура данных, над которой вы складываете (список, в случае filter), является начальной алгеброй для некоторого функтора (в данном случае, функтором списка), и ваш предикат используется для определения алгебры дляэтот функтор.

0 голосов
/ 30 мая 2018

Один интересный способ взглянуть на этот вопрос заключается в том, чтобы не выбирать filter как примитивное понятие.Существует класс типа Haskell под названием Filterable, который удачно описывается как :

Как Functor, но он [включает] Maybe эффектов.

Формально класс Filterable представляет функтор от Kleisli Maybe до Hask .

Отображение морфизма "функтора от Kleisli Maybeto Hask"захвачен методом mapMaybe класса, который действительно является обобщением одноименной функции Data.Maybe:

mapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b

Законы классов являются просто соответствующимизаконы функторов (обратите внимание, что Just и (<=<) являются, соответственно, тождеством и составом в Kleisli Maybe ):

mapMaybe Just = id
mapMaybe (g <=< f) = mapMaybe g . mapMaybe f

Этот класс также может быть выражен через catMaybes ...

catMaybes :: Filterable f => f (Maybe a) -> f a

... который можно определить с помощью mapMaybe (см. Аналогичное соотношение между sequenceA и traverse) ...

catMaybes = mapMaybe id
mapMaybe g = catMaybes . fmap g

... и представляет собой естественное преобразование между Hask endofunctors Compose f Maybe и f.

Что все это имеете делать с твоим вопросом?Во-первых, функтор - это морфизм между категориями, а естественное преобразование - это морфизм между функторами.Таким образом, здесь можно говорить о морфизмах в том смысле, что он на менее скучен, чем "морфизмы в Hask " один .Вам не обязательно хотеть сделать это, но в любом случае это существующая точка зрения.

Во-вторых, filter, что неудивительно, также метод Filterable,его определение по умолчанию:

filter :: Filterable f => (a -> Bool) -> f a -> f a
filter p = mapMaybe $ \a -> if p a then Just a else Nothing

Или, по буквам, используя другой симпатичный комбинатор :

filter p = mapMaybe (ensure p)

Это косвенно дает filter место в этом конкретномСозвездие категориальных понятий.

0 голосов
/ 30 мая 2018

filter можно записать в терминах foldRight как:

filter p ys = foldRight(nil)( (x, xs) => if (p(x)) x::xs else xs ) ys

foldRight в списках - это карта T-алгебр (где здесь T - функтор типа данных List), поэтомуfilter является отображением T-алгебр.

Здесь рассматриваются две алгебры: начальная алгебра списка

[nil, cons]: 1 + A x List(A) ----> List(A)

и, скажем, алгебра «фильтра»,

[nil, f]: 1 + A x List(A) ----> List(A)

где f(x, xs) = if p(x) x::xs else xs.

Давайте назовем filter(p, _) уникальным отображением от начальной алгебры до алгебры фильтров в этом случае (в общем случае это называется fold).Тот факт, что это карта алгебр, означает, что выполняются следующие уравнения:

filter(p, nil) = nil
filter(p, x::xs) = f(x, filter(p, xs))
0 голосов
/ 30 мая 2018

В этом ответе я предполагаю, что вы говорите о filter на Set (ситуация кажется более запутанной для других типов данных).

Давайте сначала исправим то, о чем мы говорим.Я конкретно расскажу о следующей функции (в Scala):

def filter[A](p: A => Boolean): Set[A] => Set[A] = 
                                     s => s filter p

Когда мы запишем ее таким образом, мы ясно увидим, что это полиморфная функция с параметром типа A, которая отображает предикаты A => Booleanфункциям, которые отображают Set[A] на другие Set[A].Чтобы сделать его «морфизмом», нам нужно было бы сначала найти несколько категорий, в которых эта вещь могла бы быть «морфизмом».Можно было бы надеяться, что это естественное преобразование и, следовательно, морфизм в категории эндофункторов в «стандартной по умолчанию эмбиентной структуре категории», обычно называемой «Hask» (или «Scal»? «Scala»?).Чтобы показать, что это естественно, мы должны были бы проверить, что следующая диаграмма коммутирует для каждого f: B => A:

                       - o f
Hom[A, Boolean] ---------------------> Hom[B, Boolean]
     |                                       |
     |                                       |
     |                                       |
     | filter[A]                             | filter[B]
     |                                       |
     V                  ???                  V
Hom[Set[A], Set[A]] ---------------> Hom[Set[B], Set[B]]

однако, здесь мы немедленно терпим неудачу, потому что не ясно, что даже положить на горизонтальную стрелкувнизу, поскольку присваивание A -> Hom[Set[A], Set[A]] даже не кажется функторным (по тем же причинам, почему A -> End[A] не является функторным, см. здесь , а также здесь ).

Единственная "категориальная" структура, которую я вижу здесь для fixed type A, заключается в следующем:

  • Предикаты на A можно считатьчастично упорядоченный набор с подтекстом, то есть p LEQ q, если p подразумевает q (то есть либо p(x) должно быть ложным, либо q(x) должно быть истинным для всех x: A).
  • Аналогично, для функций Set[A] => Set[A] мы можем определить частичный порядок с помощью f LEQ g всякий раз, когда для каждого набора s: Set[A] утверждается, что f(s) является подмножеством g(s).

Тогда filter[A] будет монотонным и, следовательно, функтором между категориями poset.Но это немного скучно.

Конечно, для каждого фиксированного A оно (или, скорее, его eta-расширение) также является просто функцией от A => Boolean до Set[A] => Set[A], так что это автоматически "морфизм" в "Hask -category».Но это еще скучнее.

...