记录更新如何在内部表现?

red*_*der 9 haskell

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
Run Code Online (Sandbox Code Playgroud)

当我以这种方式改变foo时复制了什么?而不是直接改变结构的一部分.

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
Run Code Online (Sandbox Code Playgroud)

使用优化进行编译是否会改变此行为?

Dan*_*her 8

在第一个示例中,将Int复制指向未更改组件的指针(以及构造函数标记,如果您希望这样说).是否Int复制了一个或一个指针是没有太大区别的,但是如果组件是大型结构,它会.

由于字段不严格,因此行为与优化无关.如果字段是严格的,并且具有优化,则可以将它们解压缩到构造函数中,然后Int#复制原始值.

在第二个示例中,没有任何内容被复制,其内容IORef被覆盖.


scl*_*clv 8

为了扩展丹尼尔的答案,你可以想到

data Foo = Foo {a::Int, b::Int}
update foo x = foo{a=x}
Run Code Online (Sandbox Code Playgroud)

就像差不多一样

data Foo = Foo Int Int
update (Foo a b) x = Foo x b
Run Code Online (Sandbox Code Playgroud)