为什么Haskell的镜头库里同时有itraverse和itraversed功能?
Why have both itraverse and itraversed functions in Haskell's lens library?
Haskell 库 lens contains a type class TraversableWithIndex that defines both the functions itraverse and 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
是两者中唯一可以与 %@~
as an 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
与 s = 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
更容易实现。通常
它已经存在(例如 containers
中的 traverseWithKey
)。
操作需要具体的光学实例
(例如 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)]]
Haskell 库 lens contains a type class TraversableWithIndex that defines both the functions itraverse and 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
是两者中唯一可以与 %@~
as an 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
与 s = 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
更容易实现。通常
它已经存在(例如 containers
中的 traverseWithKey
)。
操作需要具体的光学实例
(例如 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)]]