我们说我有一对转换函数
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的镜头库特定的答案,我会非常满意。
答案 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;进入光学框架。