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 to share