How to make a 2D slice with a lens

import qualified Data.Vector as V
import Control.Lens
import Data.Vector.Lens

v = V.fromList [V.fromList [1..3], V.fromList [4..6], V.fromList [7..9]]

      

1D slice (for example):

*Main> v ^. sliced 1 2
fromList [fromList [4,5,6],fromList [7,8,9]]

      

2D environment: what should I write to get this result?

*Main> v ^. sliced 1 2 {- ??????? -}  sliced 0 2   --  Or not so?
V.fromList [V.fromList [4,5], V.fromList [7,8]]

      

+3


source to share


1 answer


This should do it

insliced :: Int -> Int -> Lens' (V.Vector (V.Vector a)) (V.Vector (V.Vector a))
insliced i n f m = f (V.map (V.slice i n) m)
    <&> V.zipWith (\a b -> a V.// zip [i..i+n-1] (V.toList b)) m

      

then

λ v ^. sliced 1 2 . insliced 0 2
fromList [fromList [4,5],fromList [7,8]]

      

This meets the requirements for sliced

.



It's worth mentioning a general version of this here column

from linear

. It cannot be used with Vector

, because it is Vector

not Representable

(because because the size is not known statically). But with something like V3

:

λ V3 (V3 1 2 3) (V3 4 5 6) (V3 7 8 9) ^. _yz . column _xy
V2 (V2 4 5) (V2 7 8)

      

You can write your (less secure) version for vectors:

vcolumn :: ALens' a b -> Lens' (V.Vector a) (V.Vector b)
vcolumn l f m = f (V.map (^# l) m) <&> V.zipWith (\a b -> a & l #~ b) m

      

+3


source







All Articles