Haskell 阵列索引透镜阵列外和索引透镜

Haskell 阵列索引透镜阵列外和索引透镜,haskell,composition,haskell-lens,lenses,Haskell,Composition,Haskell Lens,Lenses,这是一个更简单的版本,因为我已经解决了一些问题。我不确定我是应该删除原稿还是在原处编辑它 给定 我想写一个函数 combine :: Lens' M (Array Int Int) -> Lens' M Int -> Lens' M Int 它采用arr和idx镜头,并构造一个组合镜头,可用于读取和写入idx指向的元素。我想要的镜头存在: comboGet :: M -> Int comboGet m = _arr m ! _idx m comboSet :: M ->

这是一个更简单的版本,因为我已经解决了一些问题。我不确定我是应该删除原稿还是在原处编辑它

给定

我想写一个函数

combine :: Lens' M (Array Int Int) -> Lens' M Int -> Lens' M Int
它采用
arr
idx
镜头,并构造一个组合镜头,可用于读取和写入
idx
指向的元素。我想要的镜头存在:

comboGet :: M -> Int
comboGet m = _arr m ! _idx m

comboSet :: M -> Int -> M
comboSet m v = m { _arr = _arr m // [(_idx m, v)] }

combo1 :: Simple Lens M Int
combo1 = lens comboGet comboSet
我理解原则上可以重写
comboGet
comboSet
以单独使用
arr
idx
镜头


我的问题是:用
arr
idx
构造
combo1
最惯用的方法是什么?

你可以这样构造它:

combo :: Lens' M Int -- alias for 'Functor f => (Int -> f Int) -> (M -> f M)
combo f m = arr (\xs -> fmap (\r -> xs // [(i, r)]) $ f $ xs ! i) m
  where i = m^.idx
betterCombo :: Traversal' M Int
betterCombo f m = arr (\xs -> maybe (pure xs) 
                                    ((\r -> xs // [(i, r)]) <$> f)
                                    xs^? ix i) m
  where i = m^.idx
编辑 更好的
遍历
版本如下所示:

combo :: Lens' M Int -- alias for 'Functor f => (Int -> f Int) -> (M -> f M)
combo f m = arr (\xs -> fmap (\r -> xs // [(i, r)]) $ f $ xs ! i) m
  where i = m^.idx
betterCombo :: Traversal' M Int
betterCombo f m = arr (\xs -> maybe (pure xs) 
                                    ((\r -> xs // [(i, r)]) <$> f)
                                    xs^? ix i) m
  where i = m^.idx

您可以这样构造它:

combo :: Lens' M Int -- alias for 'Functor f => (Int -> f Int) -> (M -> f M)
combo f m = arr (\xs -> fmap (\r -> xs // [(i, r)]) $ f $ xs ! i) m
  where i = m^.idx
betterCombo :: Traversal' M Int
betterCombo f m = arr (\xs -> maybe (pure xs) 
                                    ((\r -> xs // [(i, r)]) <$> f)
                                    xs^? ix i) m
  where i = m^.idx
编辑 更好的
遍历
版本如下所示:

combo :: Lens' M Int -- alias for 'Functor f => (Int -> f Int) -> (M -> f M)
combo f m = arr (\xs -> fmap (\r -> xs // [(i, r)]) $ f $ xs ! i) m
  where i = m^.idx
betterCombo :: Traversal' M Int
betterCombo f m = arr (\xs -> maybe (pure xs) 
                                    ((\r -> xs // [(i, r)]) <$> f)
                                    xs^? ix i) m
  where i = m^.idx

事实证明,作为
是部分的,
Lens'
不是一种方法,我应该使用
Traversal'

combine :: Lens' M (Array Int Int) -> Lens' M Int -> Traversal' M Int
comboGet
comboSet
可以使用镜头组合器重写:

comboGet' :: M -> Int
comboGet' m = m ^?! almostCombo m

comboSet' :: M -> Int -> M
comboSet' m v = m & almostCombo m .~ v where

almostCombo :: M -> Traversal' M Int
almostCombo m = arr . ix (m ^. idx)
@chaosmatter的组合可以写成:

combo2 :: Functor f => (Int -> f Int) -> M -> f M
combo2 f m = arr (\xs -> fmap (\r -> (ix i .~ r) xs) . f $ xs ^?! ix i) m  
    where i = m^.idx
它的
遍历
签名只会因
Applicative
而有所不同:

combo :: Applicative f => (Int -> f Int) -> M -> f M
Applicative
能否帮助我们将getter的结果设置为可选


正如@chaosmatter在他的
betterCombo
中指出的那样,关键是eta扩展镜头组成,以获得
m

,结果是As
是部分的,
Lens'
不是一种方法,我应该使用
Traversal'

combine :: Lens' M (Array Int Int) -> Lens' M Int -> Traversal' M Int
comboGet
comboSet
可以使用镜头组合器重写:

comboGet' :: M -> Int
comboGet' m = m ^?! almostCombo m

comboSet' :: M -> Int -> M
comboSet' m v = m & almostCombo m .~ v where

almostCombo :: M -> Traversal' M Int
almostCombo m = arr . ix (m ^. idx)
@chaosmatter的组合可以写成:

combo2 :: Functor f => (Int -> f Int) -> M -> f M
combo2 f m = arr (\xs -> fmap (\r -> (ix i .~ r) xs) . f $ xs ^?! ix i) m  
    where i = m^.idx
它的
遍历
签名只会因
Applicative
而有所不同:

combo :: Applicative f => (Int -> f Int) -> M -> f M
Applicative
能否帮助我们将getter的结果设置为可选


正如@chaosmatter在他的
betterCombo
中指出的那样,关键是eta扩展镜头组成,以获得
m

啊哈<代码>简单镜头
就是
Lens'
Aha<代码>简单镜头
只是
镜头
是的,你可以使用
形式
应用
进行真正的
遍历
,查看我对我答案的编辑。是的,你可以使用
形式
应用
进行真正的
遍历
,查看我对我答案的编辑。