2011-11-30 12 views
9
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 

¿Qué se copia cuando mudo foo de esta manera? A diferencia de mutar parte de una estructura directamente.¿Cómo se comportan las actualizaciones de registros internamente?

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 

¿Compilar con optimizaciones cambia este comportamiento?

+4

Algo, algo, algo, 'inseguroPerformIO'. Algo, algo, algo, completo. –

Respuesta

8

En el primer ejemplo, se copian los punteros a los componentes Int sin modificar (y la etiqueta del constructor, si usted desea decirlo). No hace mucha diferencia si se copia un Int o un puntero a uno, pero si los componentes fueran estructuras grandes, lo haría.

Dado que los campos no son estrictos, el comportamiento es, afaik, independiente de la optimización. Si los campos fueran estrictos, con optimizaciones, se podrían desempaquetar en el constructor y luego se copiarían los valores brutos Int#.

En el segundo ejemplo, no se copia nada, se sobrescribe el contenido de IORef.

8

Para ampliar la respuesta de Daniel, se puede pensar en

data Foo = Foo {a::Int, b::Int} 
update foo x = foo{a=x} 

como casi lo mismo que

data Foo = Foo Int Int 
update (Foo a b) x = Foo x b 
2

Es probablemente el caso de que la actualización de un campo de resultados en la copia de toda la estructura. Pero si el compilador puede probar que la estructura se usa de una sola manera, puede actualizarse en su lugar. No conozco ninguna implementación que haga esto, pero podría imaginarse haciendo recuentos de referencia de un solo bit.

+0

Creo que Clean lo hace ya que el sistema de tipo está integrado en un solo hilo. Clean no es una implementación de Haskell. – nponeccop

+0

Sí, Clean tiene tipos de exclusividad que les permite usar una actualización destructiva de, p. matrices. – augustss

Cuestiones relacionadas