Haskell 记录更新在内部的行为如何?
当我以这种方式变异foo时,复制了什么?而不是直接改变结构的一部分Haskell 记录更新在内部的行为如何?,haskell,Haskell,当我以这种方式变异foo时,复制了什么?而不是直接改变结构的一部分 data Thing = Thing {a :: Int, b :: Int, c :: Int, (...) , z :: Int} deriving Show foo = Thing 1 2 3 4 5 (...) 26 mkBar x = x { c = 30 } main = do print $ mkBar foo Data Thing=Thing{a::IORef Int,b::IORef Int,(…),z:
data Thing = Thing {a :: Int, b :: Int, c :: Int, (...) , z :: Int} deriving Show
foo = Thing 1 2 3 4 5 (...) 26
mkBar x = x { c = 30 }
main = do print $ mkBar foo
Data Thing=Thing{a::IORef Int,b::IORef Int,(…),z::IORef Int}
实例展示东西在哪里
(…一些不安全的东西…)
mkFoo=do a在第一个示例中,复制指向未更改的Int
组件的指针(以及构造函数标记,如果您愿意的话)。复制Int
或指向Int的指针没有多大区别,但如果组件是大型结构,则会有很大区别
由于字段不严格,因此行为与优化无关。如果字段是严格的,经过优化,它们可能会被解包到构造函数中,然后原始的Int
值会被复制
在第二个示例中,没有复制任何内容,IORef的内容被覆盖。要扩展Daniel的答案,您可以考虑
Data Thing = Thing {a :: IORef Int, b :: IORef Int, (...) , z :: IORef Int}
instance Show Thing where
(...something something unsafePerformIO...)
mkFoo = do a <- newIORef 1
(...)
z <- newIORef 26
return Thing a b (...) z
mkBar x = writeIORef (c x) 30
main = do foo <- mkFoo
mkBar foo
print foo
差不多
data Foo = Foo {a::Int, b::Int}
update foo x = foo{a=x}
更新字段可能会导致复制整个结构。但是,如果编译器能够证明该结构是以单线程方式使用的,那么它就可以进行适当的更新。我不知道有哪种实现可以做到这一点,但您可以想象使用单位引用计数来实现它 某物,某物,某物,unsafePerformIO
。某物,某物,某物,完整。我认为Clean这样做是因为它的类型系统内置了单线程。Clean不是Haskell实现。是的,Clean具有唯一性类型,允许他们使用破坏性更新,例如数组。
data Foo = Foo Int Int
update (Foo a b) x = Foo x b