Т.Л., др - Согласно вашему определению 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
Oof, ему это не понравилось. Ой, подождите, чтобы использовать 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
s.
Но traverse
работает только для подмножества Functor
s, которые также являются Applicative
. Таким образом, тип traverse
составляет более конкретно, чем разрешено для Lens
es.
Отличный ответ. Большое вам спасибо за умное решение проблемы. У меня есть один вопрос: не будет ли подпись типа 'view' стать' ((a -> Const a a) -> s -> Const a s) -> s -> a'? –
@AaditMShah, о, вы правы. Я исправлю это – bennofs