Patrzyłem talk Simon Peyton Jones' O Control.Lens, a on pokazał, że obiektyw i LensR zdefiniowane tutaj są izomorficzne:Control.Lens: przemierzania izomorfizm do toListOf i ponad
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
data LensR s t a b = LensR {
viewR :: s -> a,
setR :: b -> s -> t
}
próbuję zrobić to samo z Traversal:
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
data TraversalR s t a b = TraversalR {
toListOfR :: s -> [a],
overR :: (a -> b) -> s -> t
}
newtype CL a b = CL { getCL :: [a] } -- ConstantList
instance Functor (CL a) where
fmap _ (CL xs) = CL xs
instance Applicative (CL a) where
pure _ = CL []
(CL xs) <*> (CL ys) = CL (xs ++ ys)
travToTravR :: Traversal s t a b -> TraversalR s t a b
travToTravR tr = TraversalR {
toListOfR = getCL . tr (CL . pure),
overR = \f -> runIdentity . tr (Identity . f)
}
Ale utknąłem z travRToTrav. To jest najlepsze, co mogę wymyślić:
travRToTrav :: TraversalR s t a b -> Traversal s t a b
travRToTrav trR a2fb s = (\bs-> overR trR magic s) <$> f_bs
where as = toListOfR trR s
f_bs = sequenceA . map a2fb $ as
magic = undefined
tu magiczne :: a -> B, ale nie mogę zrobić ogólną funkcję (a -> b). Zamiast tego mogę oszukiwać, wykonując funkcję częściową: wiem, co funkcja powinna zwrócić dla dowolnej wartości typu a, która jest w ruchu. Mogę więc utworzyć listę asocjacyjną z as i bs, a następnie częściowo z tego wynikać.
Czy to działa? Jeśli tak, proszę powiedz mi, że jest lepszy sposób!
A może wybrałem niewłaściwą formę dla TraversableR, a właściwie nie ma izomorfizmu?
Dzięki za radę.
EDIT:
Więc dzięki András Kovács ja teraz myślę, że TraversalR powinna wyglądać następująco:
data TraversalR s t a b = TraversalR {
toListOfR :: s -> [a],
setListR :: [b] -> s -> t
}
Następnie travRToTrav jest bardzo podobna do lensRToLens:
travRToTrav :: TraversalR s t a b -> Traversal s t a b
travRToTrav trR a2fb s = (`setL` s) <$> f_bs
where as = toListOfR trR s
f_bs = sequenceA . map a2fb $ as
setL = setListR trR
Ale jak zdefiniować setListR w travToTravR? Zasadniczo, w jaki sposób działają indeksowane traversals?
'TraversalR' nie wydaje się dobry. Używając 'Traversal', możesz wykonać stateful traversal i e. sol. zamień każdy "a" na indeks swojej pozycji. Z '(a -> b) -> s -> t', to nie jest możliwe. –
Oh OK - nie zdawałem sobie sprawy. Jak myślisz, jak powinien wyglądać TraversalR? – RhubarbAndC
'overR :: [b] -> s -> t 'spowodowałoby, że' TraversalR' był podobny do ['biplate'] (https://hackage.haskell.org/package/uniplate-1.6.12/docs/Data -Generics-Uniplate-Operations.html # t: Biplate), więc warto spróbować. –