Im Allgemeinen ist dies unmöglich. Wahrscheinlich der häufigste Fall, wenn Sie Linsen zu verschiedenen Bereichen der Aufzeichnung haben, sind die Linsen disjunkt, so dass Sie eine rechtmäßige Linse machen können. Aber im Allgemeinen ist es nicht wahr. Aus diesem Grund ist der Kombinator nicht in den Bibliotheken enthalten, selbst wenn er einfach zu schreiben wäre.
Angenommen lensProd
existiert. Es ist genug, um zweimal die gleiche Linse zu nehmen:
_1 :: Lens' (a, b) a -- Simpler type
badLens :: Lens' (a, b) (a, a)
badLens = lensProd _1 _1
Dann wird die „Man bekommt zurück, was Sie setzen in“ Gesetz nicht gilt. Es sollte sein:
view badLens (set badLens (1, 2) (3, 4)) ≡ (1, 2)
Aber es kann nicht wahr sein, wie view badLens pair
kehrt einigen Wert zweimal: (x, x)
für all pair
s.
@dfeuer gibt ein Beispiel, wie man lensProd
definiert.
Interessanterweise ist das Dual auch gebrochen. Im Allgemeinen kann man nicht rechtmäßig Summe des Prismas haben:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Control.Lens
-- |
-- >>> :t sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a())
-- sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a())
-- :: (Applicative f, Choice p) =>
-- p (Either a()) (f (Either a())) -> p (Maybe a) (f (Maybe a))
--
sumPrism :: Prism' a b -> Prism' a c -> Prism' a (Either b c)
sumPrism ab ac = prism' build match where
build (Left b) = ab # b
build (Right c) = aC# c
match x = Left <$> x ^? ab <|> Right <$> x ^? ac
-- The law
--
-- @
-- preview l (review l b) ≡ Just b
-- @
--
-- breaks with
--
-- >>> preview badPrism (review badPrism (Right 'x'))
-- Just (Left 'x')
--
badPrism :: Prism' a (Either a a)
badPrism = sumPrism id id
Wie Sie sehen können, haben wir in Right
, aber Left
raus.
Ist das wirklich Dual? – dfeuer