When you look at setting
in lens-family-core
package, you'll find that its type is Identical f => ((a -> b) -> s -> t) -> LensLike f s t a b
, and Identical
is defined as class (Traversable f, Applicative f) => Identical f
.
I understand it needs Applicative
and Identical
as it uses pure
and extract
, but I'm not sure why it needs Traversable
.
setting :: Identical f => ((a -> b) -> s -> t) -> LensLike f s t a b
setting sec f = pure . sec (extract . f)
I also found that Setter
in lens
package had Traversable
constraint through Settable
. So I guess a setter needs Traversable
in general.
Why does a setter need Traversable
in general?
Setters don't really need Traversable
, but effectively you enforce having this constraint anyway because Identical
/ Settable
are classes that only allows trivial instances. I.e., either Identity
or something isomorphic to it, and all of these are obviously traversable as well.
Notice you could always write
idenTraverse :: (Identical t, Applicative g) => (a -> g b) -> t a -> g (t b)
idenTraverse f = fmap pure . f . extract
which is equivalent to the standard traverse
. (Actually this needs only Functor g
, incidentally.)
Explicitly requiring the standard Traversable
interface makes for a cleaner, more consistent hierarchy, without actually changing what you can or can't do with the setters.