Объектив / Призма с обработкой ошибок
Допустим, у меня есть пара функций преобразования
string2int :: String -> Maybe Int
int2string :: Int -> String
Я мог бы представить их довольно легко, используя оптику.
stringIntPrism :: Prism String Int
Однако, если я хочу представить причину сбоя, мне нужно сохранить их как две отдельные функции.
string2int :: String -> Validation [ParseError] Int
int2string :: Int -> String`
Для этого простого примера Maybe
это прекрасно, так как мы всегда можем предположить, что сбой является ошибкой разбора, поэтому нам не нужно кодировать это, используя тип Either или Validation.
Однако представьте, в дополнение к моему анализу Prism, я хочу выполнить некоторую проверку
isOver18 :: Int -> Validation [AgeError] Int
isUnder55 :: Int -> Validation [AgeError] Int
Было бы идеально иметь возможность составить эти вещи вместе, чтобы я мог иметь
ageField = isUnder55 . isOver18 . string2Int :: ValidationPrism [e] String Int
Это довольно тривиально, чтобы построить вручную, однако кажется достаточно распространенным понятием, что в области линз / оптики может быть что-то скрывающееся, которое уже делает это. Есть ли существующая абстракция, которая обрабатывает это?
ТЛ; др
Существует ли стандартный способ реализации частичной линзы / призмы / изо, который можно параметризовать через произвольный функтор, а не привязывать непосредственно к Maybe?.
Я использовал нотацию на Haskell выше, поскольку она более прямолинейна, но на самом деле я использую Monocle в Scala для реализации этого. Я, однако, был бы совершенно счастлив с ответом, специфичным для библиотеки объективов ekmett.
1 ответ
Я недавно написал сообщение в блоге об индексированной оптике; который немного исследует, как мы можем делать коэкспонированную оптику.
Короче говоря, возможна коиндексированная оптика, но нам еще предстоит провести там некоторые дополнительные исследования. Особенно потому, что если мы попытаемся перевести этот подход на lens
Кодирование линз (от Profunctor до VL) становится еще более сложным (но я думаю, что мы можем обойтись только с 7 переменными типа).
И мы не можем сделать это без изменения того, как индексированная оптика в настоящее время кодируется в lens
, Поэтому сейчас вам лучше использовать специальные библиотеки проверки.
Чтобы намекнуть на трудности: когда мы пытаемся сочинять с Traversal
с, мы должны иметь
-- like `over` but also return an errors for elements not matched
validatedOver :: CoindexedOptic' s a -> (a -> a) -> s -> (ValidationErrors, s)
или что-то другое? Если бы мы могли составить только призмы с коиндексом, их ценность не оправдала бы их сложности; они не будут "вписываться" в структуру оптики.