使用单片眼镜/scalaz镜片时的平等成本

使用单片眼镜/scalaz镜片时的平等成本,scala,scalaz,lenses,monocle-scala,Scala,Scalaz,Lenses,Monocle Scala,我读到了,它让我想到了/: 如果我(有条件地)使用/lens对深度嵌套数据结构的某些部分进行深度修改,并希望比较是否有更改,是否需要进行深度比较,或者是否有方法使用引用相等来查看两个数据结构(有条件修改前和修改后)是否相同 换句话说: val f_new=monocleiftheunisup(f_old)的修改 在数据结构的根(f_-old,f_-new)处使用引用等式(eq)可以有效地进行比较吗 换句话说, 当且仅当f\u new.eq(f\u old)为真时,f\u new==f\u old

我读到了,它让我想到了/:

如果我(有条件地)使用/lens对深度嵌套数据结构的某些部分进行深度修改,并希望比较是否有更改,是否需要进行深度比较,或者是否有方法使用引用相等来查看两个数据结构(有条件修改前和修改后)是否相同

换句话说:

val f_new=monocleiftheunisup(f_old)的修改

在数据结构的根(
f_-old
f_-new
)处使用引用等式(
eq
)可以有效地进行比较吗

换句话说,

当且仅当
f\u new.eq(f\u old)
为真时,
f\u new==f\u old
是否为真<代码>(方程式1)

若否,原因为何


如果不是,是否可以使
等式1
为真?如何返回?

也许您可以使用
modifyF
而不是
modify
来返回
选项
,这样您就不必检查是否有更改

例如:

import monocle.Lens
import monocle.macros.GenLens
import scalaz.std.option._

case class Person(name: String, address: Address)
case class Address(street: String, number: Int)

val addressL: Lens[Person, Address] = GenLens[Person](_.address)
val streetL:  Lens[Address, String] = GenLens[Address](_.street)

val changePersonsStreet: Person => Option[Person] =
  (addressL composeLens streetL).modifyF[Option] { street =>
    // only change street name if first letter comes before 'N'
    street.headOption.filter(_.toString.capitalize < "N").map(_ => "New Street")
    // or any other condition
    // if (theSunIsUp) Some("changed street name") else None
  } _

val alice = Person("Alice", Address("Main Street", 1))

val alice2: Option[Person] = changePersonsStreet(alice)
// Some(Person(Alice,Address(New Street,1)))
// -> modified, no need to check

val alice3 = alice2.flatMap(changePersonsStreet)
// None
// -> not modified
import monocle.Lens
导入monocle.macros.GenLens
导入scalaz.std.option_
案例类人员(姓名:字符串,地址:地址)
案例类别地址(街道:字符串,编号:Int)
val addressL:Lens[个人,地址]=GenLens[个人](.地址)
val streetL:Lens[地址,字符串]=GenLens[地址](uu.street)
val changePersonsStreet:Person=>选项[Person]=
(addressL composeLens street)。修改[Option]{street=>
//仅当第一个字母在“N”之前时才更改街道名称
street.headOption.filter(u.toString.capitalize<“N”).map(u=>“新街道”)
//或任何其他情况
//如果(取消)一些(“更改街道名称”),其他没有
} _
val alice=人(“alice”,地址(“Main Street”,1))
val alice2:Option[Person]=changePersonsStreet(alice)
//一些(人(爱丽丝,地址(新街1号)))
//->已修改,无需检查
val alice3=alice2.flatMap(changePersonsStreet)
//没有
//->未修改

我的经验非常有限:如果你关心性能,请完全避免使用镜头。他们让你慢了很多。不管怎样,你提出的观点很有趣,正在等待答案。还有什么选择?还有更好的选择吗?我仍然没有好的答案,但相信镜头只是一种语法糖,开销很小,这是一种错误的想法,人们会因为它的销售方式而这样想。如果您需要处理大量的类和数据结构,这是非常好的,但是对于性能来说,这并不好。但是,如果不能利用并行性,那么整个不变的方法对这一点是有害的。我对替代品感兴趣,因为我可能处于与您类似的场景中,我想知道您的问题的答案,以获取灵感,或许学习更有效地使用镜头或处理嵌套DSI。例如,我不认为Haskell中的镜头从性能角度看是不好的,实际上,它们比另一种方法(即手动模式匹配)要好。这就解释了为什么:,所以Scala中的镜头可能也是如此,我不认为它们比另一种选择(即使用复制)更糟糕。顺便说一句,这是镜头的另一种选择:,使用参考。谢谢你的回答,有趣的方法。其想法是在任意两个
之间实现快速平等比较。因此,如果有人随机给我两个
,那么只需查看引用(使用
eq
),如果他们相等,那么我知道这两个人是相同的(无需进行深入的逐值比较)。使用这种方法,如果有人给我两个随机的
选项[Person]
-s(由程序在某个时间点生成,但我不知道何时何地),那么我无法确定它们是否相同。