New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Traversing and Mapping on L1/M1/R1? #15
Comments
Hmm, I don't see how, can you explain? |
Every -- This type represents a traversal "frozen" in a format that an ArrowChoice
-- can interact with.
newtype BazE a b t = BazE {
unBazE :: Either t (a, BazE a b (b -> t))
}
-- And this type represents a traversal as a difference list, in a way that
-- makes operations O(1). It's equivalent to
-- Backwards (Curried (Yoneda (BazE a b)) (Yoneda (BazE a b))).
newtype Bazaar a b t = Bazaar {
unBazaar :: forall r y.
(forall x. ((t -> r) -> x) -> BazE a b x) ->
(r -> y) -> BazE a b y
}
instance Functor (Bazaar a b) where
fmap f (Bazaar m) = Bazaar $ \y -> m $ \c -> y $ \g -> c $ g . f
{-# INLINE fmap #-}
instance Applicative (Bazaar a b) where
pure a = Bazaar $ \y c -> y $ \g -> c $ g a
{-# INLINE pure #-}
Bazaar mf <*> Bazaar ma = Bazaar $
\y -> mf $ ma $ \c -> y $ \g -> c $ \a f -> g $ f a
{-# INLINE (<*>) #-}
-- This adds a value to the traversal.
bazaar :: a -> Bazaar a b b
bazaar a = Bazaar $ \y c -> BazE $ Right (a, y $ (.) c)
{-# INLINE bazaar #-}
-- And this turns a applicative Bazaar value into a dissectable BazE value.
runBazaar :: Bazaar a b t -> BazE a b t
runBazaar (Bazaar m) = m (\c -> BazE $ Left $ c id) id
{-# INLINE runBazaar #-}
-- This newtype is pretty much a hack so I don't have to use
-- ScopedTypeVariables.
newtype Debaz p a b = Debaz { unDebaz :: forall u. p (BazE a b u) u }
-- The Traversal type from Lens.
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
-- And now we implement wander.
wanderA :: ArrowChoice p => Traversal s t a b -> p a b -> p s t
wanderA tr p = arr (runBazaar . tr bazaar) >>> unDebaz go where
go = Debaz $
arr (either id $ uncurry $ flip id) . right (p *** unDebaz go) . arr unBazE
{-# INLINE wanderA #-} There's probably a better way, specific to |
And it turns out the naive way doesn't work, because in order to create instance Traversing M1 where
wander tr (M1 k h m) = wand k (runBazaar . tr (bazaar . h)) m where
wand :: forall s t m b. (m -> b) -> (s -> BazE m b t) -> (m -> m -> m) -> M1 s t
wand k h' m = M1 k' h' m' where
m' :: forall u. BazE m b u -> BazE m b u -> BazE m b u
m' (BazE (Right (a, b))) (BazE (Right (c, d))) = BazE $ Right (m a c, m' b d)
m' l@(BazE (Left _)) _ = l
m' _ r@(BazE (Left _)) = r
k' :: forall u. BazE m b u -> u
k' (BazE (Left u)) = u
k' (BazE (Right (a, b))) = k' b $ k a The only law I'm not sure about whether it passes is traverse' . traverse' = dimap Compose getCompose . traverse' The first one is trivially satisfied by the default definition, and the second and fourth are obvious by inspection. |
Nice! Would |
It actually appears that it would do the reverse of the current |
Just ran into a need for a generalized |
And backclosed :: M1 a b -> M1 (b -> x) (a -> x) which is necessary to map an |
L1
,M1
, andR1
areStrong
andChoice
Category
s. That should mean that there is aTraversing
instance for them. And the fact that they'reClosed
as well should mean there is aMapping
instance, too. But, while theTraversing
instance seems like it can be done fairly mechanically, I can't figure out what theMapping
instance would be.The text was updated successfully, but these errors were encountered: