Почему функция набора призмы не возвращает Option/Maybe

В функциональной оптике, призма с хорошим поведением (я полагаю, называется частичной линзой в скале) должна иметь заданную функцию типа 'subpart -> 'parent -> 'parentгде, если призма "успешна" и структурно совместима с 'parent аргумент дан, то он возвращает 'parent дано с соответствующим измененным подразделом, чтобы иметь 'subpart значение дано. Если призма "терпит неудачу" и конструктивно несовместима с 'parent аргумент, то он возвращает 'parent дано без изменений.
Мне интересно, почему призма не возвращает 'parent option (Maybe для Haskellers), чтобы представить природу / неудачу установленной функции? Разве программист не может сказать по типу возвращаемого значения, был ли набор "успешным" или нет?

Я знаю, что было проведено много исследований и размышлений в области функциональной оптики, поэтому я уверен, что должен быть окончательный ответ, который я просто не могу найти.

(Я из F# фона, поэтому я прошу прощения, если синтаксис, который я использовал, немного непрозрачен для программистов на Haskell или Scala).

2 ответа

Решение

Чтобы ответить на вопрос "почему" - линзы и т. Д. Довольно жестко выведены из теории категорий, так что это на самом деле довольно четко - описываемое вами поведение просто выпадает из математики, это не то, что кто-то определил для какой-либо цели, но следует из далекого более общие идеи.

Хорошо, это не очень приятно.

Не уверен, что системы типов других языков достаточно мощны, чтобы выразить это, но в принципе и в Haskell призма является частным случаем обхода. Обход - это способ "посетить" все вхождения "элементов" в некотором "контейнере". Классический пример

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

Это обычно используется как

Prelude> mapM print [1..4]
1
2
3
4
[(),(),(),()]

Основное внимание здесь уделяется последовательности действий / побочных эффектов и получению результата в контейнере с той же структурой, с которой мы начали.

Что особенного в призме, так это то, что контейнеры ограничены одним или нулевым элементом (тогда как общий обход может проходить через любое количество элементов). Но set Оператор не знает об этом, потому что это строго более общее. Приятно то, что вы можете использовать это на объективе, призме или mapMи всегда получаю разумное поведение. Но дело не в том, чтобы "вставить ровно один раз в структуру или сказать, не удалось ли это".

Не то чтобы это не разумная операция, просто это не то, что библиотеки линз называют "настройкой". Вы можете сделать это, явно сопоставив и перестроив:

set₁ :: Prism s a -> a -> s -> Maybe s
set₁ p x = case matching p x of
    Left _ -> Nothing
    Right a -> Just $ a ^. re p

Точнее, призма разделяет случаи: контейнер может содержать либо один элемент, и ничего кроме него, либо он может не иметь элемента, но возможно что-то не связанное.

Я сомневаюсь, что есть один окончательный ответ, поэтому я дам вам два здесь.

происхождения

Я полагаю, что призмы были впервые представлены (Дэн Доэль, если моё смутное воспоминание верно) как "линзы". В то время как объектив от s в a предложения

get :: s -> a
set :: (s, a) -> s

призма из s в a предложения

coget :: a -> s
coset :: s -> Either s a

Все стрелки перевернуты, и произведение, (,), заменен на побочный продукт, Either, Таким образом, призма в категории типов и функций является линзой в двойной категории.

Для простых призм это s -> Either s a кажется немного странным Почему вы хотите вернуть первоначальное значение? Но lens Пакет также предлагает сменную оптику. Таким образом, мы в конечном итоге

get :: s -> a
set :: (s, b) -> t

coget :: a -> s
coset :: t -> Either s b

Внезапно то, что мы получаем в случае несоответствия, может на самом деле быть немного другим! О чем это? Вот пример:

cogetLeft :: a -> Either a x
cogetLeft = Left

cosetLeft :: Either b x -> Either (Either a x) b
cosetLeft (Left b) = Right b
cosetLeft (Right x) = Left (Right x)

Во втором (не совпадающем) случае возвращаемое нами значение совпадает, но его тип был изменен.

Хорошая иерархия

Для Ван Ларховена (как в lens) и рамки стиля профессора, и линзы и призмы могут также заменять обходы. Чтобы сделать это, они должны иметь похожие формы, и этот дизайн выполняет это. Ответ leftaroundabout дает более подробную информацию по этому аспекту.

Другие вопросы по тегам