tl;dr - According to your definition of Lens
, a traverse
cannot be a Lens
because traverse
doesn't work for all Functor
s.
Let's take a look at your types:
λ :set -XRankNTypes
λ :m +Control.Applicative Data.Traversable
λ type Lens s a = Functor f => (a -> f a) -> s -> f s
λ :t traverse
traverse
:: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
Now at this point we can see that traverse
is, in one way, slightly more general than our Lens
type - it can take a function
from a -> f b
where our lens can only take functions from a -> f a
.
Restricting it to that case is no problem, so we can say
λ :t traverse :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a)
traverse :: (Traversable t, Applicative f) => (a -> f a) -> t a -> f (t a)
:: (Applicative f, Traversable t) => (a -> f a) -> t a -> f (t a)
So now it's obvious that if traverse
is to be a Lens
, it must be a Lens (t a) a
, since that's the only way to make the type variables line up.
So let's try that out.
λ :t traverse :: Lens (t a) a
<interactive>:1:1:
Could not deduce (Traversable t1) arising from a use of `traverse'
from the context (Functor f)
bound by the inferred type of
it :: Functor f => (a -> f a) -> t a -> f (t a)
at Top level
or from (Functor f1)
bound by an expression type signature:
Functor f1 => (a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
at <interactive>:1:1-24
Possible fix:
add (Traversable t1) to the context of
an expression type signature:
Functor f1 => (a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
or the inferred type of
it :: Functor f => (a -> f a) -> t a -> f (t a)
In the expression: traverse :: Lens (t a) a
Oof, it didn't like that. Oh, wait, in order to use traverse
our type t
has to be Traversable
, so let's add that restriction. (Just like the "Possible fix") suggests:
λ :t traverse :: Traversable t => Lens (t a) a
<interactive>:1:1:
Could not deduce (Applicative f1) arising from a use of `traverse'
from the context (Functor f, Traversable t)
bound by the inferred type of
it :: (Functor f, Traversable t) => (a -> f a) -> t a -> f (t a)
at Top level
or from (Traversable t1, Functor f1)
bound by an expression type signature:
(Traversable t1, Functor f1) =>
(a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
at <interactive>:1:1-41
Possible fix:
add (Applicative f1) to the context of
an expression type signature:
(Traversable t1, Functor f1) =>
(a1 -> f1 a1) -> t1 a1 -> f1 (t1 a1)
or the inferred type of
it :: (Functor f, Traversable t) => (a -> f a) -> t a -> f (t a)
In the expression: traverse :: Traversable t => Lens (t a) a
Ok, so the problem now is that it can't infer that f
is Applicative
(which is also required to use traverse
), just that it's a Functor
(which it gets from the definition of Lens
).
We can't add Applicative f
to the context though - the f
is hidden. When we say type Lens s a = Functor f => (a -> f a) -> s -> f s
, we're saying that the Lens
has to work for all Functor
s.
But traverse
only works for the subset of Functor
s that are also Applicative
. So in this way the type of traverse
is more specific than is allowed for Lens
es.
view
become((a -> Const a a) -> s -> Const a s) -> s -> a
? – Soneson