
Thanks, Felipe.
On Mon, Jul 28, 2008 at 8:01 PM, Felipe Lessa
2008/7/28 Galchin, Vasili
: and we're suggesting instead:
newtype AIOCB = AIOCB (ForeignPtr AIOCB)
^^^ I am somewhat new to Haskell. Not a total newbie! But what exactly does the above mean? Are the three references of "AIOCB" in different namespaces?
The first and the third are the type AIOCB, the second is the type constructor AIOCB. That is, it is equivalent (up to renaming) to
newtype T = C (ForeignPtr T)
Now, why use Type in Type's definition? It is obvious that if we were creating
data T = D T
it would be pretty useless, however the type that ForeignPtr requires is just a phantom type. In other words, the ForeignPtr will never use the C constructor.
An analogy to C: if you have
typeA *pa; typeB *pb;
then of course pa and pb have different types, however their internal representation are the same: an integral type of 32/64 bits. The C compiler only uses the type to provide warnings, to know the fields' offsets, the size of the structure, etc. The same goes for Haskell, if you have
pa :: ForeignPtr A pb :: ForeignPtr B
then both pa and pb have different types, but again they have the same internal representation. However, for example, if you allocate memory for pa via Storable then the compiler will find the correct sizeOf definition because will gave the type hint. The compiler also won't you let mix pa and pb like in [pa,pb].
So, if you declare
newtype T = C (ForeignPtr T)
you are:
1) Hiding the ForeignPtr from the users of your library if you don't export C. 2) Having type safeness by using ForeignPtr T instead of something generic like ForeignPtr () -- the same as using typeA* instead of void*. 3) Not needing to create a different type, like
data InternalT = InternalT newtype T = C (ForeignPtr InternalT)
Well.. did it help at all? =)
-- Felipe.