Я немного не согласен с ответом, за который проголосовали за изоморфизм, поскольку определение изоморфизма в теории категорий ничего не говорит об объектах. Чтобы понять почему, давайте рассмотрим определение.
Определение
Изоморфизм — это пара морфизмов (то есть функций) f
и g
, таких, что:
f . g = id
g . f = id
Эти морфизмы затем называются изоморфизмами. Многие люди не понимают, что «морфизм» в изоморфизме относится к функции, а не к объекту. Однако вы бы сказали, что объекты, которые они соединяют, являются «изоморфными», что и описывает другой ответ.
Обратите внимание, что определение изоморфизма не говорит, что должно быть (.
), id
или =
. Единственное требование состоит в том, чтобы, какими бы они ни были, они также удовлетворяли законам категорий:
f . id = f
id . f = f
(f . g) . h = f . (g . h)
Композиция (т. е. (.
)) объединяет два морфизма в один морфизм, а id
обозначает своего рода «тождественный» переход. Это означает, что если наши изоморфизмы сокращаются до тождественного морфизма id
, то вы можете думать о них как об инверсиях друг друга.
В конкретном случае, когда морфизмы являются функциями, id
определяется как функция тождества:
id x = x
... и состав определяется как:
(f . g) x = f (g x)
... и две функции являются изоморфизмами, если они сокращаются до функции тождества id
, когда вы их составляете.
Морфизмы против объектов
Однако есть несколько способов, которыми два объекта могут быть изоморфны. Например, для следующих двух типов:
data T1 = A | B
data T2 = C | D
Между ними есть два изоморфизма:
f1 t1 = case t1 of
A -> C
B -> D
g1 t2 = case t2 of
C -> A
D -> B
(f1 . g1) t2 = case t2 of
C -> C
D -> D
(f1 . g1) t2 = t2
f1 . g1 = id :: T2 -> T2
(g1 . f1) t1 = case t1 of
A -> A
B -> B
(g1 . f1) t1 = t1
g1 . f1 = id :: T1 -> T1
f2 t1 = case t1 of
A -> D
B -> C
g2 t2 = case t2 of
C -> B
D -> A
f2 . g2 = id :: T2 -> T2
g2 . f2 = id :: T1 -> T1
Вот почему лучше описывать изоморфизм в терминах конкретных функций, связывающих два объекта, а не два объекта, поскольку между двумя объектами не обязательно может существовать уникальная пара функций, удовлетворяющая законам изоморфизма.
Также обратите внимание, что недостаточно, чтобы функции были обратимыми. Например, следующие пары функций не являются изоморфизмами:
f1 . g2 :: T2 -> T2
f2 . g1 :: T2 -> T2
Несмотря на то, что при составлении f1 . g2
информация не теряется, вы не возвращаетесь в исходное состояние, даже если конечное состояние имеет тот же тип.
Кроме того, изоморфизмы не обязательно должны быть между конкретными типами данных. Вот пример двух канонических изоморфизмов не между конкретными алгебраическими типами данных, а вместо этого просто связывающих функции: curry
и uncurry
:
curry . uncurry = id :: (a -> b -> c) -> (a -> b -> c)
uncurry . curry = id :: ((a, b) -> c) -> ((a, b) -> c)
Использование изоморфизмов
Церковное кодирование
Одним из способов использования изоморфизмов является кодирование по Черчу типов данных как функций. Например, Bool
изоморфно forall a . a -> a -> a
:
f :: Bool -> (forall a . a -> a -> a)
f True = \a b -> a
f False = \a b -> b
g :: (forall a . a -> a -> a) -> Bool
g b = b True False
Убедитесь, что f . g = id
и g . f = id
.
Преимущество типов данных, кодирующих Черч, заключается в том, что они иногда работают быстрее (поскольку кодирование Черча является стилем передачи продолжения) и могут быть реализованы на языках, которые вообще не имеют языковой поддержки для алгебраических типов данных.
Перевод реализаций
Иногда кто-то пытается сравнить реализацию какой-либо функции в одной библиотеке с реализацией в другой библиотеке, и если вы можете доказать, что они изоморфны, то вы можете доказать, что они одинаково эффективны. Кроме того, изоморфизмы описывают, как перевести одну библиотеку в другую.
Например, есть два подхода, которые позволяют определить монаду по сигнатуре функтора. Одна из них — свободная монада, предоставляемая пакетом free
, а другая — операционная семантика, предоставляемая пакетом operational
.
Если вы посмотрите на два основных типа данных, они выглядят по-разному, особенно их вторые конструкторы:
-- modified from the original to not be a monad transformer
data Program instr a where
Lift :: a -> Program instr a
Bind :: Program instr b -> (b -> Program instr a) -> Program instr a
Instr :: instr a -> Program instr a
data Free f r = Pure r | Free (f (Free f r))
... но на самом деле они изоморфны! Это означает, что оба подхода одинаково эффективны, и любой код, написанный в одном подходе, может быть механически переведен в другой подход с использованием изоморфизмов.
Изоморфизмы, не являющиеся функциями
Кроме того, изоморфизмы не ограничиваются функциями. На самом деле они определены для любого Category
, а в Haskell существует множество категорий. Вот почему полезнее думать с точки зрения морфизмов, а не типов данных.
Например, тип Lens
(от data-lens
) образует категорию, в которой можно составлять линзы и иметь индивидуальную линзу. Таким образом, используя приведенный выше тип данных, мы можем определить две линзы, которые являются изоморфизмами:
lens1 = iso f1 g1 :: Lens T1 T2
lens2 = iso g1 f1 :: Lens T2 T1
lens1 . lens2 = id :: Lens T1 T1
lens2 . lens1 = id :: Lens T2 T2
Обратите внимание, что в игре есть два изоморфизма. Одним из них является изоморфизм, который используется для построения каждой линзы (т. е. f1
и g1
) (и именно поэтому эта функция построения называется iso
), а затем сами линзы также являются изоморфизмами. Обратите внимание, что в приведенной выше формулировке используемая композиция (.
) является не функциональной композицией, а скорее композицией линз, а id
не является функцией идентичности, а вместо этого является линзой идентичности:
id = iso id id
Это означает, что если мы составим наши две линзы, результат должен быть неотличим от той линзы идентичности.
person
Gabriel Gonzalez
schedule
28.06.2012
iso-
означает равный (/эквивалентный): en.wiktionary.org/wiki/iso-#Etymology и-morph-
означает форму/форму: thefreedictionary.com/morph. Таким образом, изоморфизм — это отношение/функция эквивалентности между двумя типами, как их можно определить, уже очень хорошо объяснено ниже. - person Cetin Sert   schedule 30.06.2012