在功能光学中,行为良好的棱镜(我相信在斯卡拉称为局部透镜)应该具有'subpart -> 'parent -> 'parent类型的设定函数,如果该棱镜“成功”并且在结构上与给定的'parent参数兼容,则它返回修改了适当子部分以提供'parent值的给定的'subpart。如果棱镜“发生故障”并且在结构上与'parent参数不兼容,则它将返回未经修改的'parent
我想知道为什么棱镜不返回'parent option(Haskellers的Maybe)来表示set函数的通过/失败性质?程序员不应该从返回类型中判断出该集合是否“成功”吗?

我知道功能光学领域已经进行了很多研究和思考,因此我敢肯定,肯定有一个我似乎找不到的明确答案。

(我来自F#背景,因此对于Haskell或Scala程序员使用的语法有点不透明,我深表歉意。)

最佳答案

要回答“为什么”-镜头等都是严格地归类于类别理论的,所以这实际上是很明确的-您所描述的行为只是从数学中删除的,不是任何人为任何目的定义的东西,而是很远的地方更一般的想法。

好吧,那真的不令人满意。

不确定其他语言的类型系统是否足够强大来表达这一点,但是原则上在Haskell中,棱镜是遍历的一种特殊情况。
遍历是一种“访问”某些“容器”中所有“元素”出现的方式。经典的例子是

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

这通常像

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

这里的重点是:对 Action /副作用进行排序,然后将结果收集到一个与我们开始时的结构相同的容器中。

棱镜的特殊之处在于,容器被限制为只能包含一个或零个元素†(而一般遍历可以遍历任何数量的元素)。但是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

†更精确地:用棱镜将箱子分开:一个容器可能包含一个元素,除此之外没有别的东西,或者它可能没有元素,但可能不相关。

关于scala - 为什么棱镜设置函数不返回Option/也许,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46384203/

10-10 05:54