非法镜头 Haskell
Posted
技术标签:
【中文标题】非法镜头 Haskell【英文标题】:unlawful lens Haskell 【发布时间】:2021-03-30 05:52:54 【问题描述】:对于不满足取出您放入的物品的属性的类似镜头的物体,是否有一个通用名称/类型?例如像 listLength :: Lens [a] Int
这样的东西,如果你输入的长度比源列表的长度短,你会得到一个缩短的列表,但如果你输入的长度更长,原始长度会被保留。
【问题讨论】:
你能想出你希望这样一个对象具有的属性吗?例如。如果你把你拿出的东西放进去,你什么都没有改变? @luqui 我只是想知道是否有任何记录的概念包含我的示例非法镜头。 您所说的与partsOf 非常相似,只要保持某些不变量,它就会将遍历变成镜头。您可以在该函数的文档中看到注释,但他们实际上并没有命名这个想法。 【参考方案1】:镜头不仅仅是forall f. Functor f => (a -> f b) -> s -> f t
类型的函数——它是一个符合特定规律的函数。特别是(如记录的in the lens docs):
-
你会取回你投入的东西,
收回你所得到的并不会改变任何事情,并且
设置两次与设置一次相同。
如果你的函数不遵守这些规律,那么它只是一个类型类似于镜头的函数。
在您的特定示例中,listLength
违反了第一和第三定律,因此它不是镜头。也就是说,它可以作为 Getter
正常工作,我认为这是我们可以说的唯一原则。
更一般地说,询问那些缺乏规律的事物是没有意义的,因为事物往往是由它们遵守的法律而非不遵守的法律来定义的。例如,我指出listLength
是一个非常好的Getter
,因为它始终从[a]
输入中提取一个值。
那么,我会问你:它与总是发出 0
的函数 listZero :: Lens [a] Int
有什么区别?你能想出一个listLength
遵守listZero
不遵守的一般规律吗?如果是这样,那么您可以在当前文献中实际寻找一些东西:也就是说,listLength
是一组遵守某些(可能很有趣)定律的函数之一。如果不是,那么您只有一个类型的函数,使它看起来像一个镜头。
【讨论】:
listLength
遵循标准的往返半定律,而 listZero
可能不会,这取决于它对“放置”方向的实现。有问题的法律是这样的:如果put v x = v'
,那么put v' (get v') = v'
。在一些较早的文献中,遵守两个往返半定律就足以称一个事物为镜头。表现良好的镜片也服从您的(1)和(2);现在可以从lens
包中获得的符合您所有三个定律的东西被称为行为良好的镜头。以上是关于非法镜头 Haskell的主要内容,如果未能解决你的问题,请参考以下文章