Control.Lens.Setter在Haskell中使用Observable功能非常出色。 (更新数据集中的值时将触发函数/功能键。)
但是,考虑到镜头不包含在标准环境中,然后需要在不使用镜头的情况下进行额外安装,而我只想使用原始的设置功能(例如带有字段标签)
data Foo = Foo {val :: Int}
该怎么做?
ST Monad是否适合此目的?
谢谢。
答案 0 :(得分:4)
在此处查找的内容不是很清楚,但是如果您只想更新记录字段,则可以使用Haskell记录更新语法:
x = Foo { val = 5 }
y = x { val = 42 }
这适用于具有任意数量字段的任何记录,并且您无需列出所有字段,只需列出要更新的字段即可,例如:
data D = D { a :: String, b :: Int }
x = D { a = "foo", b = 42 }
y = x { a = "bar" } -- now y = D { a = "bar", b = 42 }
z = x { b = 43 } -- now z = D { a = "foo", b = 43 }
请记住,这实际上并不是对内存中的值进行 update (“更改”,“变异”),而是创建具有所有内容的记录的副本除更新的字段外,其他字段均与原始记录的字段相同。镜头的工作方式相同,事实上,Haskell的所有功能都可以做到,因为Haskell根本不允许突变。
答案 1 :(得分:4)
我认为您在一些概念之间有些困惑;具体来说,是塞特犬还是可观察者。
setName
(用于一条记录),并且使用类似setName "foo" oldRecord
的名称来调用它,则将保持oldRecord
不变,但会返回一个带有名称设置为"foo"
。如您所知,还有其他更复杂的设置器实现,例如镜头。现在要回答您的另一个问题:如何使用不带镜头的安装员?好吧,如果您有一个像data Foo = Foo {val :: Int, val2 :: String}
这样的记录(您的示例+一个额外的字段),并且您有一个旧记录-假设oldRecord = Foo { val = 1, val2 = "test" }
,Haskell具有特殊的setter语法:做oldRecord { val = 2 }
将给出一个{strong> new 记录,其中val
设置为2
-也就是说,它将给出Foo { val = 2, val2 = "test" }
。显然,对于嵌套记录,此语法有点笨拙,这是镜头被发明的原因。