Orc*_*lev 6 haskell list lenses
我正在尝试对包含元素列表的嵌套数据结构进行操作.在用各种方法解决之后,我终于决定使用镜头作为最好的方法.它们完美地用于查找和修改结构的特定元素,但到目前为止,我对如何添加新元素感到困惑.
从我读过的内容来看,我无法在技术上使用Traversal,因为它违反了Traversal定律,将新元素插入到列表中,并且假设我甚至可以首先使用Traversal找出如何做到这一点(我对Haskell仍然相当弱,并且镜头包装中大多数东西的类型签名让我头晕目眩.
具体来说,我想要完成的是,在匹配特定选择器的元素列表中找到一些元素,然后在匹配元素之前或之后插入一个新元素(函数的不同参数在之前或之后)比赛).Control.Lens是否已经拥有可以完成我正在尝试做的事情,而且我对类型签名的理解太弱而无法看到它?有没有更好的方法来完成我想要做的事情?
如果我只是想在列表的开头或结尾添加一个新元素,那么这将是相当微不足道的,但是将它插入特定于中间的某个地方是困难的部分.在我编写的一些前镜头代码中,我使用折叠来完成我想要的东西,但它开始变得粗糙在结构的更深嵌套部分(EG折叠内部的折叠内部)所以我转向Control.Lens试图解开一些混乱.
使用镜头 pacakge
如果我们开始知道该功能id
可以像镜头一样使用:
import Control.Lens
> [1,2,3,4] ^. id
[1,2,3,4]
Run Code Online (Sandbox Code Playgroud)
然后我们可以继续讨论如何修改列表:
> [1,2,3,4] & id %~ (99:)
[99,1,2,3,4]
Run Code Online (Sandbox Code Playgroud)
以上允许在列表的开头插入.专注于我们可以用列表的后面部分_tail
从Control.Lens.Cons模块.
> [1,2,3,4] ^. _tail
[2,3,4]
> [1,2,3,4] & _tail %~ (99:)
[1,99,2,3,4]
Run Code Online (Sandbox Code Playgroud)
现在将其概括为第n个位置
> :{
let
_drop 0 = id
_drop n = _tail . _drop (n - 1)
:}
> [1,2,3,4] ^. _drop 1
[2,3,4]
> [1,2,3,4] & _drop 0 %~ (99:)
[99,1,2,3,4]
> [1,2,3,4] & _drop 1 %~ (99:)
[1,99,2,3,4]
Run Code Online (Sandbox Code Playgroud)
最后一步超过所有类型的一个概括这种Cons
情况下,我们可以使用cons
或<|
.
> [1,2,3,4] & _drop 1 %~ (99<|)
[1,99,2,3,4]
> import Data.Text
> :set -XOverloadedStrings
> ("h there"::Text) & _drop 1 %~ ('i'<|)
"hi there"
Run Code Online (Sandbox Code Playgroud)
我认为一个简单的方法可以将问题分解为:
[a] -> SomeAddtionalData -> [a]
,它基本上负责使用一些特定数据将列表转换为另一个列表。您可以在此处添加/删除列表中的元素并获取新列表你的最后一段说明了当你尝试使用像 Lens 这样的通用抽象做太多事情时会发生什么。这些通用抽象适用于某些通用目的,而其他所有内容都特定于您的问题,并且应该围绕普通的旧函数进行设计(至少在最初,稍后在您的项目中,您可能会在代码库中发现一些通用模式,可以使用以下方式进行抽象)类型类等)。