Scala 带误差处理的透镜/棱镜

Scala 带误差处理的透镜/棱镜,scala,haskell,haskell-lens,lenses,monocle-scala,Scala,Haskell,Haskell Lens,Lenses,Monocle Scala,假设我有一对转换函数 string2int :: String -> Maybe Int int2string :: Int -> String 我可以用光学很容易地表示这些 stringIntPrism::Prism String Int 然而,如果我想表示失败原因,我需要将它们作为两个单独的函数 string2int :: String -> Validation [ParseError] Int int2string :: Int -> String` 对于这个

假设我有一对转换函数

string2int :: String -> Maybe Int
int2string :: Int -> String
我可以用光学很容易地表示这些

stringIntPrism::Prism String Int

然而,如果我想表示失败原因,我需要将它们作为两个单独的函数

string2int :: String -> Validation [ParseError] Int
int2string :: Int -> String`
对于这个简单的例子,
也许
是非常好的,因为我们总是可以假设一个失败是一个解析失败,因此我们实际上不必使用非此即彼或验证类型来编码它

然而,想象一下,除了解析棱镜之外,我还想执行一些验证

isOver18 :: Int -> Validation [AgeError] Int
isUnder55 :: Int -> Validation [AgeError] Int
如果能把这些东西组合在一起,这样我就可以

ageField=低于55。18岁以上。string2Int::ValidationPrism[e]字符串Int

这是相当琐碎的手工制作,但它似乎是一个足够普遍的概念,在镜头/光学领域可能已经有了一些潜在的东西。是否存在处理此问题的现有抽象

tl;博士

是否有一种标准的方法来实现部分透镜/棱镜/iso,它可以在任意函子上参数化,而不是直接绑定到Maybe

我在上面使用了Haskell符号,因为它更直接,但实际上我使用Scala中的Monocle来实现这一点。然而,我非常乐意得到一个关于ekmett透镜库的具体答案。

我最近写了一篇关于索引光学的文章;这也探索了一点我们如何制作共索引光学

简言之:共指数光学是可能的,但我们还没有做一些进一步的研究。特别是,如果我们尝试将这种方法转换为透镜的编码(从Profunctor到VL),它会变得更加复杂(但我认为我们可以只使用7个类型变量)

如果不改变索引光学元件当前在
镜头中的编码方式,我们就无法真正做到这一点。所以现在,您最好使用特定于验证的库

提示一下困难:当我们尝试使用
Traversal
s进行创作时,我们应该

-- like `over` but also return an errors for elements not matched
validatedOver :: CoindexedOptic' s a -> (a -> a) -> s -> (ValidationErrors, s)

还是别的什么?如果我们只能够组合出共索引棱镜,它们的价值将无法证明它们的复杂性;它们无法“适应”光学框架。

我记得很久以前reddit讨论过一个类似的问题。在这本书中,爱德华·科米特(Edward Kmett)介绍了一种“共索引棱镜”(coindexed prisms),它能够报告错误信息,同时保持与普通透镜的组合。显然,由于类型推断问题,它们很难适应lens框架,因此它们没有实现。我认为遍历的概念在这里是合适的。