gpt4 book ai didi

haskell - 为自定义镜头编写类别实例

转载 作者:行者123 更新时间:2023-12-02 21:32:44 25 4
gpt4 key购买 nike

我一直在读这篇文章article用于理解镜头。我知道这不同于Edward Knett 的镜头包,但尽管如此,它对于基础知识很有用。

所以,镜头的定义如下:

type Lens a b = (a -> b, b -> a -> a)

有人提到镜头形成一个类别,我一直在尝试为 Category 类型类创建实例。首先,我编写函数的类型定义:

(.) :: Lens y z -> Lens x y -> Lens x z
id :: Lens x x

此后,我就盯着它看一整天。到底是什么编写其定义的思维过程?

最佳答案

我找到了这个article (约瑟夫·亚伯拉罕森(Joseph Abrahamson)从头开始的 fpcomplete 镜头)要非常好,它从与您开始使用的镜头相同的表示开始,为其定义构图,并继续沿着与 lens 更相似的表示的路径前进。

编辑:我发现在做这种事情时类型孔非常好:

(<.>):: Lens y z -> Lens x y -> Lens x z
(getA,setA) <.> (getB,setB) = (_,_)

现在我们有 2 个孔,元组中的第一个表示(输出已清理):

Found hole ‘_’ with type: x -> z
...
Relevant bindings include
setB :: y -> x -> x
getB :: x -> y
setA :: z -> y -> y
getA :: y -> z
(<.>) :: Lens y z -> Lens x y -> Lens x z

仔细观察绑定(bind),我们已经拥有了我们需要的东西! getB::x -> ygetA::y -> z 以及函数组合 (.)::(b -> c) -> ( a -> b) -> a -> c

所以我们很高兴插入这个:

(<.>):: Lens y z -> Lens x y -> Lens x z
(getA,setA) <.> (getB,setB) = (getA . getB, _)

然后继续第二种类型的洞,它说:

Found hole ‘_’ with type: z -> x -> x
Relevant bindings include
setB :: y -> x -> x
getB :: x -> y
setA :: z -> y -> y
getA :: y -> z

我们最相似的东西是 setA::z -> y -> y,我们首先插入一个 lambda,捕获参数:

(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> _)

将您的类型孔更改为:

Found hole ‘_’ with type: x
Relevant bindings include
x :: x
z :: z
setB :: y -> x -> x
getB :: x -> y
setA :: z -> y -> y
getA :: y -> z

我们可以插入x,它会进行类型检查,但不会给我们想要的东西(设置时什么也不会发生)。唯一可以为我们提供 x 的其他绑定(bind)是 setB,因此我们插入:

(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> setB _ _)

我们的第一种类型的洞说:

Found hole ‘_’ with type: y
Relevant bindings include
x :: x
z :: z
setB :: y -> x -> x
getB :: x -> y
setA :: z -> y -> y
getA :: y -> z

所以我们需要一个 y,查看范围内的内容,如果我们给它一个 xgetB 可以给我们一个 y,我们碰巧有,但这会导致我们的镜头再次无用。另一种方法是使用 setA:

(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> setB (setA _ _) _)

(从现在开始加快速度)同样,第一个洞想要 z 类型的东西,他恰好将其作为我们的 lambda 的参数:

(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> setB (setA z _) _)

要填充 y 类型的第一个类型洞,我们可以使用 getB::x -> y 为其提供 lambda 的参数:

(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> setB (setA z (getB x)) _)

这给我们留下了一个剩余的类型孔,可以轻松地用 x 替换它,从而得到最终的定义:

(<.>):: Lens y z -> Lens x y -> Lens x z
(getA,setA) <.> (getB,setB) = (getA . getB, \z x -> setB (setA z (getB x)) x)

您可以尝试为自己定义id,如有必要,可以使用类型孔和hoogle

关于haskell - 为自定义镜头编写类别实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22404939/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com