根据你对
Lens
的定义,
traverse
不能成为
Lens
,因为
traverse
不适用于所有的
Functor
。
让我们看一下你的类型:
λ :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)
现在我们可以看到,从某种程度上讲,
traverse
比我们的
Lens
类型略为通用——它可以接受一个从
a -> f b
的函数,而我们的镜头只能接受从
a -> f a
的函数。
将其限制在这种情况下没有问题,因此我们可以说:
λ :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)
现在显然,如果 traverse
要成为一个 Lens
,它必须是一个 Lens (t a) a
,因为这是唯一使类型变量对齐的方法。
让我们试试这个方法。
λ :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
糟糕,它不喜欢那个。哦,等等,为了使用traverse
,我们的类型t
必须是Traversable
,因此让我们添加该限制。(就像“可能的修复”建议的那样):
λ :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
好的,现在的问题是它无法推断f
是Applicative
(使用traverse
也需要),只能知道它是一个Functor
(从Lens
的定义中得到)。
然而,我们无法将Applicative f
添加到上下文中 - 因为f
被隐藏了。当我们说type Lens s a = Functor f => (a -> f a) -> s -> f s
时,我们意思是Lens
必须适用于所有Functor
。
但是,traverse
仅适用于那些同时是Applicative
和Functor
的Functor
的子集。因此,在这种情况下,traverse
的类型比Lens
允许的类型更具体。
view
的类型签名不会变成((a -> Const a a) -> s -> Const a s) -> s -> a
吗? - Aadit M Shah