tl; dr - Nach Ihrer Definition von Lens
kann ein traverse
nicht ein Lens
weil traverse
nicht für alle Functor
s nicht.
Lassen Sie uns einen Blick auf Ihre Arten nehmen:
λ :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)
An diesem Punkt können wir sehen, dass traverse
ist, in einer Art und Weise, etwas allgemeiner als unsere Lens
Art - es ist eine Funktion übernehmen kann von a -> f b
, wo unser Objektiv nur Funktionen von a -> f a
übernehmen kann.
es zu diesem Fall Beschränkung ist kein Problem, so können wir also jetzt
λ :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)
sagen, es ist offensichtlich, dass, wenn traverse
ein Lens
sein, es ist ein Lens (t a) a
sein muss, denn das ist der einzige Weg zu machen Die Typvariablen stehen in einer Linie.
Also lasst uns das ausprobieren.
λ :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, es mochte das nicht. Oh, warte, um traverse
zu verwenden, muss unser Typ t
Traversable
sein, also fügen wir diese Einschränkung hinzu.(Genau wie die „Mögliche fix“) schlägt vor:
λ :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 dass das Problem ist jetzt, dass es nicht ableiten kann, dass f
ist Applicative
nur (was auch erforderlich ist traverse
zu verwenden), dass es ein Functor
ist (was es von der Definition von Lens
erhält).
Wir können Applicative f
jedoch nicht zum Kontext hinzufügen - die f
ist ausgeblendet. Wenn wir type Lens s a = Functor f => (a -> f a) -> s -> f s
sagen, sagen wir, dass die Lens
für alleFunctor
s arbeiten muss.
Aber traverse
funktioniert nur für die Teilmenge von Functor
s, die auch Applicative
sind. Auf diese Weise ist der Typ traverse
genauer als für Lens
es zulässig ist.
Große Antwort. Vielen Dank für eine kluge Lösung des Problems. Ich habe allerdings eine Frage: Würde die Typ-Signatur von 'view' nicht' ((a -> Const a a) -> s -> Const a s) -> s -> a '? –
@AaditMShah oh, du hast Recht. Ich werde das korrigieren – bennofs