[英]Isomorphism lenses
我会对van Laarhoven的同构镜头的一个小例子感兴趣,应用于数据类型如data BValue = BValue { π :: Float, σ :: Float, α :: Float } deriving Show
(具体来说,get / set /修改功能)。 先感谢您。
从van Laarhoven的帖子来看, Lens
类型是
data Lens a b = forall r . Lens (Iso a (b, r))
所以在我们的例子中, a
是BValue
,我们想构建一些选择一个或多个元素的leneses。 例如,让我们构建一个能够挑出π的镜头。
piLens :: Lens BValue Float
所以它将是一个从BValue
到Float
的镜头(即三重中的第一个镜头,带有标签pi。)
piLens = Lens (Iso {fw = piFwd, bw = piBwd})
镜头选择了两个东西:残差类型r
(这里省略,因为我们不必在haskell中明确指定存在类型),以及同构。 同构又由前向和后向函数组成。
piFwd :: BValue -> (Float, (Float, Float))
piFwd (BValue {pi, sigma, alpha}) = (pi, (sigma, alpha))
forward函数只是隔离了我们想要的组件。 请注意,我的剩余类型是“值的其余部分”,即一对sigma和alpha浮点数。
piBwd :: (Float, (Float, Float)) -> BValue
piBwd (pi, (sigma, alpha)) = BValue { pi = pi, sigma = sigma, alpha = alpha }
后向功能类似。
所以现在我们已经定义了一个镜头来操纵BValue
的pi组件。
其他七个镜头是相似的。 (7个镜头:选择西格玛和阿尔法,挑出所有可能的对(无视顺序),挑出所有的BValue
并选择()
)。
我不确定的一点是严格:我有点担心我写的fw和bw函数太严格了。 不确定。
我们还没有完成:
我们仍然需要检查piLens
真的尊重镜头规律。 van Laarhoven对Lens
定义的好处在于我们只需要检查同构定律; 透镜法则通过他博客文章中的计算得出。
所以我们的证明义务是:
fw piLens . bw piLens = id
bw piLens . fw piLens = id
这两个证据都直接遵循piFwd
和piBwd
的定义以及关于组成的定律。
从fclabels包中查看Data.Label ,它实现了记录类型的镜头。
为了说明这个包,让我们采用以下两个示例数据类型。
import Data.Label import Prelude hiding ((.), id) data Person = Person { _name :: String , _age :: Int , _isMale :: Bool , _place :: Place } data Place = Place { _city , _country , _continent :: String }
两种数据类型都是记录类型,所有标签都以下划线为前缀。 这个下划线表示我们的Template Haskell代码可以为这些字段派生镜头。 使用这种简单的单线程可以完成透镜的衍生:
$(mkLabels [''Person, ''Place])
对于所有标签,将创建镜头。
现在让我们来看看这个例子。 这个71岁的老人,我的邻居叫Jan,他不介意以他为例:
jan :: Person jan = Person "Jan" 71 True (Place "Utrecht" "The Netherlands" "Europe")
当我们想要确定Jan真的和他声称的一样古老时,我们可以使用get函数将年龄作为整数来表示:
hisAge :: Int hisAge = get age jan
考虑一下他现在想搬到阿姆斯特丹:有什么更好的地方度过你过去的日子。 使用组合我们可以更改结构内部的城市值:
moveToAmsterdam :: Person -> Person moveToAmsterdam = set (city . place) "Amsterdam"
现在:
ghci> moveToAmsterdam jan Person "Jan" 71 True (Place "Amsterdam" "The Netherlands" "Europe")
使用(。)运算符完成组合,该运算符是Control.Category模块的一部分。 确保导入此模块并隐藏Haskell Prelude中的默认(。),id函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.