棱镜或仿射遍历的对偶是什么?
What is the dual of a prism or an affine traversal?
A 棱镜 是一种用于聚焦副产品类型的光学器件,而 affine traversal 是一种可以聚焦在 0 of 1 元素的光学器件,即 AffineTraversal s t a b
同构于 (s -> Maybe a, (s, b) -> t)
。据我所知,如果使用适当的棱镜编码,当透镜由棱镜组成时,我们会得到仿射遍历。
我有兴趣将那个(天真的)公式中的 Maybe
移动到 setter 侧而不是 getter 侧,这样我就可以拥有一个始终只提取一个元素,但可能无法将其放回。
我的用例与优化类型有关。想象一下,我们有一个类型 A
及其细化 B
(B ⊆ A
)。然后是一个棱镜refined :: Prism' A B
:一个A
可能是也可能不是一个有效的B
,但是每个B
都可以re
进入一个A
.结合 Lens' C A
和 refined
,我们有一个仿射遍历。在另一个方向,人们可以想象一个比 re refined
稍微聪明一点的光学器件 unrefined
:一个 A
可以变成 Just b
,如果它是一个有效的 B
或 Nothing
,如果不是。现在,如果我们将 Lens' C B
与 unrefined
结合起来,我们就有了对偶仿射遍历:它总是可以从 C
获得 A
,但放回任何旧的 A
可能会违反 C
的不变量并产生 Nothing
而不是 Just c
。更复杂的不变量可以用类似的方式保证。
有趣的是,Scala 的 monocle 库提供了细化类型的棱镜,但没有提供反向的棱镜。
我很难为这些 (s -> a, b -> Maybe t)
和 (s -> a, (s, b) -> Maybe t)
小玩意想出规律,我想知道更抽象的光学公式是否有帮助。
我知道有了profunctor镜头,我们有
type Lens s t a b = forall p. Strong p => p a b -> p s t
type Prism s t a b = forall p. Choice p => p a b -> p s t
type AffineTraversal s t a b = forall p. (Strong p, Choice p) => p a b -> p s t
这非常清楚,透镜放大到乘积类型,棱镜放大到余积类型,仿射遍历能够放大到代数数据类型(乘积或余积,不少于此)。
答案是否与 Cochoice
甚至 Costrong
相关(从 profunctor 中删除乘积/副积而不是引入它)?我无法从他们那里恢复天真的公式,但是...
这是一半的答案,显示了 Cochoice
光学元件和 (s -> a, b -> Maybe t)
之间的对应关系。
{-# LANGUAGE RankNTypes #-}
module P where
import Data.Profunctor
import Control.Monad
data P a b s t = P (s -> a) (b -> Maybe t)
instance Profunctor (P a b) where
dimap f g (P u v) = P (u . f) (fmap g . v)
instance Cochoice (P a b) where
unleft (P u v) = P (u . Left) (v >=> v') where
v' (Left t) = Just t
v' (Right _) = Nothing
type Coprism s t a b = forall p. Cochoice p => p a b -> p s t
type ACoprism s t a b = P a b a b -> P a b s t
fromCoprism :: ACoprism s t a b -> P a b s t
fromCoprism p = p (P id Just)
toCoprism :: P a a s t -> Coprism s t a a
toCoprism (P u v) = unleft . dimap f g where
f (Left s) = u s
f (Right a) = a
g b = case v b of
Nothing -> Right b
Just t -> Left t
A 棱镜 是一种用于聚焦副产品类型的光学器件,而 affine traversal 是一种可以聚焦在 0 of 1 元素的光学器件,即 AffineTraversal s t a b
同构于 (s -> Maybe a, (s, b) -> t)
。据我所知,如果使用适当的棱镜编码,当透镜由棱镜组成时,我们会得到仿射遍历。
我有兴趣将那个(天真的)公式中的 Maybe
移动到 setter 侧而不是 getter 侧,这样我就可以拥有一个始终只提取一个元素,但可能无法将其放回。
我的用例与优化类型有关。想象一下,我们有一个类型 A
及其细化 B
(B ⊆ A
)。然后是一个棱镜refined :: Prism' A B
:一个A
可能是也可能不是一个有效的B
,但是每个B
都可以re
进入一个A
.结合 Lens' C A
和 refined
,我们有一个仿射遍历。在另一个方向,人们可以想象一个比 re refined
稍微聪明一点的光学器件 unrefined
:一个 A
可以变成 Just b
,如果它是一个有效的 B
或 Nothing
,如果不是。现在,如果我们将 Lens' C B
与 unrefined
结合起来,我们就有了对偶仿射遍历:它总是可以从 C
获得 A
,但放回任何旧的 A
可能会违反 C
的不变量并产生 Nothing
而不是 Just c
。更复杂的不变量可以用类似的方式保证。
有趣的是,Scala 的 monocle 库提供了细化类型的棱镜,但没有提供反向的棱镜。
我很难为这些 (s -> a, b -> Maybe t)
和 (s -> a, (s, b) -> Maybe t)
小玩意想出规律,我想知道更抽象的光学公式是否有帮助。
我知道有了profunctor镜头,我们有
type Lens s t a b = forall p. Strong p => p a b -> p s t
type Prism s t a b = forall p. Choice p => p a b -> p s t
type AffineTraversal s t a b = forall p. (Strong p, Choice p) => p a b -> p s t
这非常清楚,透镜放大到乘积类型,棱镜放大到余积类型,仿射遍历能够放大到代数数据类型(乘积或余积,不少于此)。
答案是否与 Cochoice
甚至 Costrong
相关(从 profunctor 中删除乘积/副积而不是引入它)?我无法从他们那里恢复天真的公式,但是...
这是一半的答案,显示了 Cochoice
光学元件和 (s -> a, b -> Maybe t)
之间的对应关系。
{-# LANGUAGE RankNTypes #-}
module P where
import Data.Profunctor
import Control.Monad
data P a b s t = P (s -> a) (b -> Maybe t)
instance Profunctor (P a b) where
dimap f g (P u v) = P (u . f) (fmap g . v)
instance Cochoice (P a b) where
unleft (P u v) = P (u . Left) (v >=> v') where
v' (Left t) = Just t
v' (Right _) = Nothing
type Coprism s t a b = forall p. Cochoice p => p a b -> p s t
type ACoprism s t a b = P a b a b -> P a b s t
fromCoprism :: ACoprism s t a b -> P a b s t
fromCoprism p = p (P id Just)
toCoprism :: P a a s t -> Coprism s t a a
toCoprism (P u v) = unleft . dimap f g where
f (Left s) = u s
f (Right a) = a
g b = case v b of
Nothing -> Right b
Just t -> Left t