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<代码>简单镜头
只是镜头
是的,你可以使用纯
形式应用
进行真正的遍历
,查看我对我答案的编辑。是的,你可以使用纯
形式应用
进行真正的遍历
,查看我对我答案的编辑。