处理错误的镜头/棱镜

时间:2015-11-28 14:21:02

标签: scala haskell lens lenses monocle-scala

我们说我有一对转换函数

string2int :: String -> Maybe Int
int2string :: Int -> String

我可以使用Optics轻松代表这些。

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

手工制作这一点相当简单,但是它似乎是一个普遍存在的概念,在镜头/光学领域潜藏着可能存在的东西。是否存在处理此问题的现有抽象?

TL;博士

是否有一种实现部分镜头/棱镜/ iso的标准方法,可以通过任意仿函数进行参数化,而不是直接绑定到Maybe?。

我之前使用过Haskell符号,因为它比较直接,但是我实际上在Scala中使用Monocle来实现它。但是,对于ekmett的镜头库特定的答案,我会非常满意。

1 个答案:

答案 0 :(得分:5)

我最近写过关于索引光学的a blog post;这也探讨了我们如何做硬核光学。

简而言之:Coindexed-optics是可能的,但我们还没有在那里做进一步的研究。特别是,因为如果我们尝试将这种方法转换为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)

还是其他什么?如果我们只能组成Coindexed Prisms,那么它们的价值就不能证明它们的复杂性;他们不会适应"#34;进入光学框架。