标签: lenses

哪些语言支持镜头或类似的方式来更新不可变的嵌套结构?

虽然许多人称赞不变性,但我发现在主流编程中难以维持.根据我的经验,程序员迟早会使字段再次变异,以避免重构大部分代码,这些代码必须传递更新的对象以及返回值.

Scala对复制构造函数有一些支持,但我知道没有令人满意的解决方案来更新复杂的对象结构.我可能错过了什么.

我实验过的最好的实现是Haskell中的数据镜头.但是,Haskell很难学.流行的跨平台编程语言(如Java或Scala)有哪些选择?

java scala immutability lenses

8
推荐指数
1
解决办法
1336
查看次数

是否可以使用镜头构建新记录?

如果我有一个带镜头的记录类型,是否可以在不使用基础记录访问器的情况下构建新记录?

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens
import Control.Lens.TH

data Foo = Foo { _s :: String
               , _b :: Bool
               } deriving (Show, Eq)

makeLenses ''Foo
Run Code Online (Sandbox Code Playgroud)

可以制作Foo一个实例,Data.Default然后def用镜头修改,但并非所有记录类型都有合理的默认值.Control.Lens有自己的方法吗?

haskell lenses

8
推荐指数
1
解决办法
648
查看次数

Clojure中的identity函数与Haskell中的id函数具有相同的用法和用途吗?

在Clojure中我们有这个identity功能.它使用如下:

user=> (filter identity [1 2 3 nil 4 false true 1234])
(1 2 3 4 true 1234)

user=> (partition-by identity (sort "abcdaabccc"))
((\a \a \a) (\b \b) (\c \c \c \c) (\d))
Run Code Online (Sandbox Code Playgroud)

从我在Haskell中看到的内容 - id 在使用镜头时使用,并用于其他更高阶的功能.

我的问题是(除了明显的类型系统的差异)是否identityClojure中的函数具有相同用途和目的为id在Haskell功能?

为什么我要问的是当我在Clojure中查看以下Lens的示例时- 我们看到的Id定义如下functor:

(defprotocol Functor
    (fmap [functor f] "fmap :: f a -> (a -> b) -> f b"))

;; data …
Run Code Online (Sandbox Code Playgroud)

haskell identity clojure lenses

8
推荐指数
1
解决办法
1047
查看次数

镜头进入Swift属性

有没有办法在Swift中为类中的属性自动生成getter/setter函数对?在Haskell中沿着镜头的线条.

我已经能够手动执行以下操作:

class PropertyLens<U, T> {
    let getter: U -> T
    let setter: (U, T) -> ()

    init(getter: (U -> T), setter: ((U, T) -> ())) {
        self.getter = getter
        self.setter = setter
    }

    func get(u: U) -> T {
        return getter(u)
    }

    func set(u: U, t: T) {
        setter(u, t)
    }
}
// ...
let myPropertyLens = PropertyLens<MyClass, Int>(getter: { $0.myProperty }, setter: { $0.myProperty = $1 })
Run Code Online (Sandbox Code Playgroud)

然而,这比我想要的更冗长,乏味,更容易出错.是否有我缺少的内置功能?

lenses swift

8
推荐指数
1
解决办法
549
查看次数

使用镜头作为`map`

我想将这行代码转换map (^?! ix 0) [[0, 1], [4, 5], [9, 1]]成完全使用镜头,所以像[[0, 1], [4, 5], [9, 1]] & each . ix 0.但是,类型不匹配.这样做的正确方法是什么?

haskell lenses

8
推荐指数
2
解决办法
195
查看次数

高效优雅地从案例类结构的List中删除元素

我有一个嵌套的case类结构List

为简单起见,请使用以下示例 -

case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, addresses: List[Address])
case class Department(people: List[Person])
Run Code Online (Sandbox Code Playgroud)

说有List[Department]; 现在,如果我想List[Department]通过过滤Address每个Person没有特定zipCode值的新东西来创建一个新的; 传统上我们可以做到以下

def filterPersonsByAddress(dlist: List[Department]): List[Department] = {
  dlist.map { d =>
    val people = d.people.map { p => 
      p.copy(addresses = p.addresses.filterNot(_.zipCode == 38978))}
      d.copy(people=people)
    }
 }
Run Code Online (Sandbox Code Playgroud)

这种方法不具备性能,因为取决于嵌套级别,它可以是Big O(n ^ 2)或Big O(n ^ 3);

我试图通过Monocle学习镜头.到目前为止,我学到的是当你必须"修改"一个深层嵌套的case类结构但尚未找到一种方法根据条件"切断"嵌套结构的某些部分并返回一个新结构时,镜头很有用.这可能是通过Monocle吗?此外,我不确定Lenses是否能够帮助实现更好的Big O时间?

scala lenses monocle-scala

8
推荐指数
1
解决办法
612
查看次数

使用Monocle Lenses使用另一个属性的值修改属性

我有以下型号

import monocle.macros.Lenses
import monocle.function.all._
import monocle.std.list._

@Lenses("_") case class Poll(pollChoices: List[PollChoice], totalVoteCount: Int)
@Lenses("_") case class PollChoice(id: Int, value: Int, percentage: Int)
Run Code Online (Sandbox Code Playgroud)

我想要实现的是通过更新pollChoices列表中每个元素的所有百分比属性来更新Poll的pollChoices属性.我的问题是,新的百分比值是基于价值的属性PollChoicetotalValueCount中的投票.

到目前为止我所做的是:

val poll = Poll(List(PollChoice(1,3,0), PollChoice(2,5,0)), 8)

(Poll._pollChoices composeTraversal each composeLens PollChoice._percentage)
  .modify(oldPercentage => oldPercentage + 1)(poll)
Run Code Online (Sandbox Code Playgroud)

但是这样我只能访问我在修改步骤中更新的元素的百分比属性,我也需要该值.

我假设我需要使用Traversable来进行这种修改,但我不确定如何.谢谢.

scala lenses monocle

8
推荐指数
1
解决办法
105
查看次数

为什么prism set函数不返回Option/Maybe

在功能光学中,一个表现良好的棱镜(在scala中称为部分透镜,我相信)应该具有类型的函数'subpart -> 'parent -> 'parent,其中如果棱镜"成功"并且在结构上与'parent给定的参数兼容,则它返回'parent给定适当的子部分,修改为'subpart给定值.如果棱镜"失败"并且在结构上与'parent参数不相容,那么它将返回'parent给定的未修改.
我想知道为什么棱镜不返回'parent option(Maybe对于Haskellers)来表示set函数的通过/失败性质?程序员是否应该能够从返回类型中判断该集合是否"成功"?

我知道在功能光学领域已经进行了大量的研究和思考,所以我肯定必须有一个我似乎无法找到的确定答案.

(我来自F#背景,所以如果我使用的语法对Haskell或Scala程序员来说有点不透明,我很抱歉).

f# haskell functional-programming scala lenses

8
推荐指数
2
解决办法
217
查看次数

什么是棱镜或仿射遍历的双重性?

棱镜为聚焦到联产品类型的光学部件,而仿射遍历是一种光学器件的可聚焦于0 1的元件,即,AffineTraversal s t a b是同构的(s -> Maybe a, (s, b) -> t).据我所知,如果镜头由棱镜组成,我们会得到一个仿射遍历,只要使用适当的棱镜编码.

我感兴趣的是将Maybe那个(幼稚)配方移动到设置器侧而不是吸气器侧,这样我就可以使用一个总是提取一个元素的光学元件,但可能无法将它放回去.

我的用例与细化类型有关.想象一下,我们有一个类型A及其细化B(B ? A).然后有一个棱镜refined :: Prism' A B:一个A可能或可能不是有效的B,但每个B都可以re进入一个A.结合了Lens' C Arefined,我们有一个仿射遍历.在另一个方向上,可以想象一个光学元件unrefined比一个光学元件更聪明re refined:如果它是有效的,A可以变成一个光学元件,或者如果它不是,则可以变成光学元件.现在,如果我们结合了有,我们有我们的双仿射穿越:它可以随时获得从,但放回任何旧的可能违反的不变和产量,而不是.可以以类似的方式确保更复杂的不变量.Just bBNothingLens' C BunrefinedACACNothingJust c

有趣的是,Scala 的单片机 …

haskell category-theory lenses haskell-lens

8
推荐指数
1
解决办法
223
查看次数

Control.Lens这个名字背后的原因是什么?

爱德华·克梅特(Edward Kmett)的光学图书馆;Control.Lens定义了大量类型。

其中大多数具有相对自我解释的名称,例如TraversalFold

它还定义了一些名称不那么明显的类型,例如Bazaar

在“义卖市场”页面上:

aka索引的笛卡尔商店comonad,索引的Kleene商店comonad或索引的FunList。

...

通常,集市上有很多商店,您可以轻松添加更多。

我无法弄清楚Market类型名称背后的原因。我认为这在某种程度上也与商店monads / comonads有关?它是否正确?

haskell terminology lenses haskell-lens

8
推荐指数
1
解决办法
157
查看次数