关于组成索引镜头的困惑
Confusion about composing indexed lens
我可以为具有常量索引的列表创建一个 IndexedTraversal
,如下所示:
constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b
constIndexedList _ _ [] = pure []
constIndexedList index f (x:xs) = (:) <$> Lens.indexed f index x <*> constListIndex index f xs
我宁愿通过组合两个更简单的镜头来创建它:
constIndex :: i -> Lens.AnIndexedLens i a b a b
constIndex index f = Lens.indexed f index
constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b
constIndexedList index = Lens.cloneLens (constIndex index) <. traverse
然而,这无法进行类型检查,lens
中的类型错误不是我容易理解的类型错误:
• Couldn't match type ‘Lens.Indexed
i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b))’
with ‘[a] -> Lens.Bazaar (Lens.Indexed i) a b [b]’
Expected type: Lens.Indexed
i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b))
-> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b]
Actual type: ([a] -> Lens.Bazaar (Lens.Indexed i) a b [b])
-> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b]
• In the first argument of ‘(<.)’, namely
‘Lens.cloneLens (constIndex index)’
In the expression: Lens.cloneLens (constIndex index) <. traverse
为什么我不能像这样合成索引镜头?
我最终找到了一种不同的模块化方法来做到这一点(Lens.reindexed (const index) Lens.traversed
,但我仍然想知道为什么上面提到的方法不起作用..
(<.)
期望在其左侧有一个索引光学元件,但 cloneLens
给它一个未索引的镜头。
一个部分修复是使用 Lens.cloneIndexedLens
而不是 cloneLens
。
但是,A_
/An_
光学变量 (AnIndexedLens
) 是参数类型,而不是结果类型,它可以使用常规光学变量 (IndexedLens
).这样一来,cloneIndexedLens
就变得不必要了。
constIndex :: i -> Lens.IndexedLens i a b a b
constIndex i f = Lens.indexed f i
constIndexedList :: i -> Lens.IndexedTraversal i [a] [b] a b
constIndexedList i = constIndex i <. traverse
单态输入和多态输出提高了可组合性。
IndexedLens
是多态类型(注意类型定义中的 forall
关键字)。
type IndexedLens i s t a b = forall f p. (Indexable i p, Functor f) => p a (f b) -> s -> f t
AnIndexedLens
是单态的。
type AnIndexedLens i s t a b = Optical (Indexed i) (->) (Pretext (Indexed i) a b) s t a b
每个 IndexedLens
都是 AnIndexedLens
,但另一种方式的转换必须经过明确的 cloneIndexedLens
。
我可以为具有常量索引的列表创建一个 IndexedTraversal
,如下所示:
constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b
constIndexedList _ _ [] = pure []
constIndexedList index f (x:xs) = (:) <$> Lens.indexed f index x <*> constListIndex index f xs
我宁愿通过组合两个更简单的镜头来创建它:
constIndex :: i -> Lens.AnIndexedLens i a b a b
constIndex index f = Lens.indexed f index
constIndexedList :: i -> Lens.AnIndexedTraversal i [a] [b] a b
constIndexedList index = Lens.cloneLens (constIndex index) <. traverse
然而,这无法进行类型检查,lens
中的类型错误不是我容易理解的类型错误:
• Couldn't match type ‘Lens.Indexed
i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b))’
with ‘[a] -> Lens.Bazaar (Lens.Indexed i) a b [b]’
Expected type: Lens.Indexed
i (t0 a) (Lens.Bazaar (Lens.Indexed i) a b (t0 b))
-> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b]
Actual type: ([a] -> Lens.Bazaar (Lens.Indexed i) a b [b])
-> [a] -> Lens.Bazaar (Lens.Indexed i) a b [b]
• In the first argument of ‘(<.)’, namely
‘Lens.cloneLens (constIndex index)’
In the expression: Lens.cloneLens (constIndex index) <. traverse
为什么我不能像这样合成索引镜头?
我最终找到了一种不同的模块化方法来做到这一点(Lens.reindexed (const index) Lens.traversed
,但我仍然想知道为什么上面提到的方法不起作用..
(<.)
期望在其左侧有一个索引光学元件,但 cloneLens
给它一个未索引的镜头。
一个部分修复是使用 Lens.cloneIndexedLens
而不是 cloneLens
。
但是,A_
/An_
光学变量 (AnIndexedLens
) 是参数类型,而不是结果类型,它可以使用常规光学变量 (IndexedLens
).这样一来,cloneIndexedLens
就变得不必要了。
constIndex :: i -> Lens.IndexedLens i a b a b
constIndex i f = Lens.indexed f i
constIndexedList :: i -> Lens.IndexedTraversal i [a] [b] a b
constIndexedList i = constIndex i <. traverse
单态输入和多态输出提高了可组合性。
IndexedLens
是多态类型(注意类型定义中的 forall
关键字)。
type IndexedLens i s t a b = forall f p. (Indexable i p, Functor f) => p a (f b) -> s -> f t
AnIndexedLens
是单态的。
type AnIndexedLens i s t a b = Optical (Indexed i) (->) (Pretext (Indexed i) a b) s t a b
每个 IndexedLens
都是 AnIndexedLens
,但另一种方式的转换必须经过明确的 cloneIndexedLens
。