Nat*_*son 8 f# haskell functional-programming scala lenses
在功能光学中,一个表现良好的棱镜(在scala中称为部分透镜,我相信)应该具有类型的集函数'subpart -> 'parent -> 'parent,其中如果棱镜"成功"并且在结构上与'parent给定的参数兼容,则它返回'parent给定适当的子部分,修改为'subpart给定值.如果棱镜"失败"并且在结构上与'parent参数不相容,那么它将返回'parent给定的未修改.
我想知道为什么棱镜不返回'parent option(Maybe对于Haskellers)来表示set函数的通过/失败性质?程序员是否应该能够从返回类型中判断该集合是否"成功"?
我知道在功能光学领域已经进行了大量的研究和思考,所以我肯定必须有一个我似乎无法找到的确定答案.
(我来自F#背景,所以如果我使用的语法对Haskell或Scala程序员来说有点不透明,我很抱歉).
dfe*_*uer 12
我怀疑有一个确定的答案,所以我会在这里给你两个.
我相信棱镜首先被想象(由Dan Doel,如果我模糊的回忆是正确的)作为"共同镜头".而从镜头s到a报价
get :: s -> a
set :: (s, a) -> s
Run Code Online (Sandbox Code Playgroud)
从棱镜s到a报价
coget :: a -> s
coset :: s -> Either s a
Run Code Online (Sandbox Code Playgroud)
所有箭头都颠倒了,产品(,)被副产品取代Either.因此,类型和功能类别中的棱镜是双重类别中的镜头.
对于简单的棱镜,这s -> Either s a看起来有点奇怪.你为什么要回原价?但该lens封装还提供了类型变换光学器件.所以我们最终得到了
get :: s -> a
set :: (s, b) -> t
coget :: a -> s
coset :: t -> Either s b
Run Code Online (Sandbox Code Playgroud)
突然之间,我们在不匹配的情况下得到的回报可能实际上有点不同!那是什么意思?这是一个例子:
cogetLeft :: a -> Either a x
cogetLeft = Left
cosetLeft :: Either b x -> Either (Either a x) b
cosetLeft (Left b) = Right b
cosetLeft (Right x) = Left (Right x)
Run Code Online (Sandbox Code Playgroud)
在第二种(不匹配)的情况下,我们得到的值是相同的,但它的类型已经改变.
对于Van Laarhoven(如同lens)和profunctor风格的框架,镜头和棱镜也可以代替穿越.要做到这一点,他们需要有类似的形式,这种设计可以实现这一点.leftaroundabout的答案提供了有关这方面的更多细节.
lef*_*out 10
回答"为什么" - 镜头等非常严格地从类别理论中得出,所以这实际上非常明确 - 你所描述的行为只是从数学中剔除,它不是任何人为任何目的定义的东西,而是从远处来看更一般的想法.
好吧,那真的不太令人满意.
不确定其他语言的类型系统是否足够强大来表达这一点,但原则上在Haskell中,棱镜是遍历的特例.遍历是一种"访问"某些"容器"中所有"元素"出现的方法.经典的例子是
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
Run Code Online (Sandbox Code Playgroud)
这通常用作
Prelude> mapM print [1..4]
1
2
3
4
[(),(),(),()]
Run Code Online (Sandbox Code Playgroud)
这里的重点是:对动作/副作用进行排序,并将结果收集到一个与我们开始时具有相同结构的容器中.
棱镜的特殊之处在于容器被限制为包含一个或零个元素†(而一般遍历可以覆盖任意数量的元素).但是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
Run Code Online (Sandbox Code Playgroud)
† 更确切地说:棱镜分离案件:一个容器可能包含一个元素,除此之外别无其他任何东西,或者它可能没有元素但可能没有相关的东西.
| 归档时间: |
|
| 查看次数: |
217 次 |
| 最近记录: |