
Hi all, I'm looking at some code that defines a record: data Position = Position { posOffset :: {-# UNPACK #-} !Int , posRow :: {-# UNPACK #-} !Int , posColumn :: {-# UNPACK #-} !Int } What does the the exclamation mark mean? And UNPACK? Thanks in advance. Cheers, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- Microsoft is finally bringing all of its Windows operating system families under one roof. It will combine all of the features of CE, stability and support of ME and the speed of NT. It will be called Windows CEMENT...

On 26 Feb 2009, at 11:42, Erik de Castro Lopo wrote:
Hi all,
I'm looking at some code that defines a record:
data Position = Position { posOffset :: {-# UNPACK #-} !Int , posRow :: {-# UNPACK #-} !Int , posColumn :: {-# UNPACK #-} !Int }
What does the the exclamation mark mean? And UNPACK?
The ! means "strict" – i.e. don't store a thunk for an Int here, but evaluate it first. The {-# UNPACK #-} tells the compiler that it can unpack the Int – meaning that a Position will be neatly packed into 12 bytes. Bob

"Thomas" == Thomas Davie
writes:
Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes. What would be the difference if there was no UNPACK pragma? -- Colin Adams Preston Lancashire

On 26 Feb 2009, at 12:07, Colin Paul Adams wrote:
"Thomas" == Thomas Davie
writes: Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes.
What would be the difference if there was no UNPACK pragma?
The tag in the Ints would be included in the structure created, with UNPACK, they would not. Bob

"Thomas" == Thomas Davie
writes:
Thomas> On 26 Feb 2009, at 12:07, Colin Paul Adams wrote:
"Thomas" == Thomas Davie
writes: >> Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes. >> >> What would be the difference if there was no UNPACK pragma?
Thomas> The tag in the Ints would be included in the structure Thomas> created, with UNPACK, they would not. What is the tag? -- Colin Adams Preston Lancashire

On Thu, Feb 26, 2009 at 8:07 AM, Colin Paul Adams
"Thomas" == Thomas Davie
writes: Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes.
What would be the difference if there was no UNPACK pragma?
For example, if you write valid :: Position -> Bool valid (Position o r c) = o < r && c < 80 It is just an example, not necessarily meaningful :). If you use the UNPACK pragmas, then internally the compiler will create something like valid :: Int# -> Int# -> Int# -> Bool valid o r c = o <# r && c <# 80 Basically the three integers will be passed on registers. Without the UNPACK, they would be passed on the heap. Without the strictness annotation, a pointer on the heap would be passed to them (i.e. a pointer on the register would point to the Position structure which would have a pointer to the integer, not very nice). HTH, PS: I'm not sure if the unboxed operations I wrote are correct, but you get the idea :). -- Felipe.

Am Donnerstag, 26. Februar 2009 12:07 schrieb Colin Paul Adams:
"Thomas" == Thomas Davie
writes: Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes.
What would be the difference if there was no UNPACK pragma?
Section 8.12.10 of the users' guide says: "The UNPACK indicates to the compiler that it should unpack the contents of a constructor field into the constructor itself, removing a level of indirection." It has more, and also says when it's not a good idea to use it. Int is defined as data Int = I# Int# where Int# is a raw machine int. If you use the {-# UNPACK #-} pragma, you tell GHC that you'd very much like Position to be stored as constructor + three contiguous raw machine integers. Mostly, it will do so. If you don't use the pragma, i.e. have data Position = Position { posOffset :: !Int , posRow :: !Int , posColumn :: !Int } , GHC may or may not decide to store it thus, with -O2 it's not too unlikely, I think. But it's also not unlikely that it will be stored as constructor + three pointers to three evaluated Ints, which is much better than pointers to thunks, but not as good as having the raw values directly by the constructor. Cheers, Daniel

On Thu, Feb 26, 2009 at 11:33 AM, Daniel Fischer
Am Donnerstag, 26. Februar 2009 12:07 schrieb Colin Paul Adams:
> "Thomas" == Thomas Davie
writes: Thomas> The {-# UNPACK #-} tells the compiler that it can unpack Thomas> the Int – meaning that a Position will be neatly packed Thomas> into 12 bytes.
What would be the difference if there was no UNPACK pragma?
Section 8.12.10 of the users' guide says: "The UNPACK indicates to the compiler that it should unpack the contents of a constructor field into the constructor itself, removing a level of indirection."
It has more, and also says when it's not a good idea to use it.
Int is defined as
data Int = I# Int#
where Int# is a raw machine int. If you use the {-# UNPACK #-} pragma, you tell GHC that you'd very much like Position to be stored as constructor + three contiguous raw machine integers. Mostly, it will do so. If you don't use the pragma, i.e. have
data Position = Position { posOffset :: !Int , posRow :: !Int , posColumn :: !Int }
, GHC may or may not decide to store it thus, with -O2 it's not too unlikely, I think. But it's also not unlikely that it will be stored as constructor + three pointers to three evaluated Ints, which is much better than pointers to thunks, but not as good as having the raw values directly by the constructor.
Cheers, Daniel _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Are there any guarantees here, or is it just me telling the compiler to please do what I say, but the compiler can decide not to follow my wishes? Is address aligning predictable? I'm basically wondering if it'd be possible to to use this mechanism to avoid using FFI when reading data that basically is a dump of structs in a C program. /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus@therning.org http://therning.org/magnus identi.ca|twitter: magthe

Am Donnerstag, 26. Februar 2009 12:36 schrieb Magnus Therning:
Are there any guarantees here, or is it just me telling the compiler to please do what I say, but the compiler can decide not to follow my wishes?
I don't think there are guarantees, as the section ends with: "If a field cannot be unpacked, you will not get a warning, so it might be an idea to check the generated code with -ddump-simpl. See also the -funbox-strict-fields flag, which essentially has the effect of adding {-# UNPACK #-} to every strict constructor field." But it should be very likely to do what you want (of course, always compile with -O or -O2).
Is address aligning predictable?
Absolutely no idea, sorry.
I'm basically wondering if it'd be possible to to use this mechanism to avoid using FFI when reading data that basically is a dump of structs in a C program.
I doubt it, as I understand it, with {-# UNPACK #-}, you'll have the layout constuctor rawdata and the C structs won't have the constructor.
/M
Cheers, Daniel
participants (6)
-
Colin Paul Adams
-
Daniel Fischer
-
Erik de Castro Lopo
-
Felipe Lessa
-
Magnus Therning
-
Thomas Davie