Transition to zipper with `to` lens

I struggle with lens and zippers . Consider the below code in ghci

 > import Control.Lens > import Control.Zipper > > :t within (ix 1) $ zipper ([1,2,3] :: [Int]) > within (ix 1) $ zipper ([1,2,3] :: [Int]) :: Control.Monad.MonadPlus m => m (Zipper Top Int [Int] :>> Int) 

Having data A t = A t , how can I create a type of zipper type: Control.Monad.MonadPlus m => m (Zipper Top Int [Int] :>> A Int) ?

I tried within (ix 1 . to A) $ zipper ([1,2,3] :: [Int]) , but it gave an error:

 Could not deduce (Contravariant (Bazaar (Indexed Int) (A Int) (A Int))) arising from a use of 'to' from the context (Control.Monad.MonadPlus m) bound by the inferred type of it :: Control.Monad.MonadPlus m => m (Zipper Top Int [Int] :>> A Int) at Top level In the second argument of '(.)', namely 'to A' In the first argument of 'within', namely '(ix 1 . to A)' In the expression: within (ix 1 . to A) 
+6
source share
1 answer

One way is to make Iso and compose with it. In ghci:

 > import Control.Lens > import Control.Zipper > > data A t = A t > let _A = iso A (\(A a) -> a) > > let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) > :ta a :: MonadPlus m => m (Zipper Top Int [Int] :>> A Int) > a ^? _Just . focus Just (A 2) 

Edit: the reason you need (\(A a) -> a) means you can come back.

 > data A t = A t > let _A = iso A (error "Can't unA") > > let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) > a ^? _Just . focus Just (A 2) > fmap upward a ^? _Just . focus Just [1,*** Exception: Can't unA 

I don't think there is a valid way to do this without a function to extract A You can write an invalid Traversal , but it still won’t work properly:

 > data A t = A t > let _A fa = a <$ f (A a) > > let a = within (ix 1 . _A) $ zipper ([1,2,3] :: [Int]) > let b = a & _Just . focus .~ A 10 > b ^? _Just . focus Just (A 10) > fmap upward b ^? _Just . focus Just [1,2,3] -- Should be Just [1, 10, 3] 
+2
source

Source: https://habr.com/ru/post/980708/


All Articles