Haskell库镜头包含一个类型类TraversableWithIndex,它定义了itraverse和itraversed两个函数:
class
(FunctorWithIndex i t, FoldableWithIndex i t, Traversable t)
=> TraversableWithIndex i t | t -> i where
itraverse :: Applicative f => (i -> a -> f b) -> t a -> f (t b)
itraversed :: IndexedTraversal i (t a) (t b) a b
IndexedTraversal
扩展如下:
type IndexedTraversal i s t a b =
forall p f. (Indexable i p, Applicative f) => p a (f b) -> s -> f t
itraverse
并且itraversed
看起来非常相似。为什么两者都需要?
从玩弄itraverse
和itraversed
,似乎itraversed
是可以与使用两个唯一一个%@~
作为AnIndexedSetter
。
出于完整性考虑%@~
,以下是AnIndexedSetter
,和的类型Indexed
:
(%@~) :: AnIndexedSetter i s t a b -> (i -> a -> b) -> s -> t
type AnIndexedSetter i s t a b =
Indexed i a (Identity b) -> s -> Identity t
newtype Indexed i a b = Indexed { runIndexed :: i -> a -> b }
为什么%@~
要求AnIndexedSetter
?为什么Indexed
仍然必须使用?
Indexed
由于它不是正常功能,因此使用似乎会使合成更加困难。我在这里想念什么?
索引光学元件不像常规光学元件那么简单。常规Traversal
很简单:
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
这正是traverse
withs = c a
和的类型t = c b
,其中c
是Traversable
。
您可以想象IndexedTraversal i
与相似(i -> a -> f b)
;但事实并非如此!
type IndexedTraversal i s t a b =
forall p f. (Indexable i p, Applicative f) => p a (f b) -> s -> f t
该Indexable i p
约束是满足(->)
和Indexed
,所以:
itraverse :: Applicative f => (i -> a -> f b) -> s -> f t
itraversed :: Applicative f => (a -> f b) -> s -> f t -- (->)
itraversed :: Applicativef => Indexed i a b -> s -> f t
哪里
newtype Indexed i a b = Indexed { runIndexed :: i -> a -> b }
为什么两者都需要?itraverse
更容易实现。通常它已经在那里(例如traverseWithKey
中的containers
)。
业务的需要,光学系统的具体实例(如set
需要ASetter
)。很快:由于我们不使用,因此编译器更容易找出问题Rank2Types
。
Indexed
即newtype
需要分开,这样我们就可以讨论a -> b
和i -> a -> b
作为实例Indexable
; 让我们将分度光学元件降级为常规光学元件:
Prelude Control.Lens> over itraversed (+1) [1,2,3]
[2,3,4]
让p a (f b) -> q s (f t)
(p
可以是(->)
或Indexable
)组成索引光学和常规光学:
Prelude Control.Lens> over (itraversed . traversed) (+1) [[1,2],[3]]
[[2,3],[4]]
要么
Prelude Control.Lens> iover (itraversed . traversed) (,) [[1,2],[3]]
[[(0,1),(1,2)],[(0,3)]]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句