Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Haskell-cafe] Nice addition to Foreign: castAny

0 views
Skip to first unread message

Maurí­cio CA

unread,
Oct 26, 2009, 10:49:16 PM10/26/09
to haskel...@haskell.org
This could be beside castPtr, castCharToCChar etc.

----

castAny :: (Storable a, Storable b) => a -> b
castAny = unsafePerformIO . genericCast
where
genericCast :: (Storable a, Storable b) => a -> IO b
genericCast v = return undefined >>= \r ->
allocaBytes (max (sizeOf v) (sizeOf r)) $ \p ->
poke p v >> if False then return r else peek (castPtr p)

----

GHCi:

> let a = -1000 :: Int16
> castAny a :: Word16 -->
64536
> castAny a :: Ptr ()
0xb4c2fc18
> castAny (castAny a :: Ptr ()) :: Int16
-1000

> let b = pi :: CLDouble
> b
3.141592653589793
> castAny b :: CInt
1413754136
> castAny b :: Ptr ()
0x54442d18
> castAny b :: CFloat
3.3702806e12
> castAny b :: Int8
24


At minimum, this is safer than 'unsafeCoerce'. What do you think?

Best,
Maur�cio

_______________________________________________
Haskell-Cafe mailing list
Haskel...@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

John Meacham

unread,
Nov 3, 2009, 11:35:04 PM11/3/09
to haskel...@haskell.org

Try it on a big endian architecture, or one that has alignment
restrictions, or a different size for HsChar or so forth. Casting by
'punning' (as the C folks like to call it) does have uses, but they are
generally hardware dependent and useful only in certain rare
circumstances that a generic cast probably isn't likely to fill.

John

--
John Meacham - ⑆repetae.net⑆john⑈ - http://notanumber.net/

Maurí­cio CA

unread,
Nov 7, 2009, 11:48:17 PM11/7/09
to haskel...@haskell.org
>> castAny :: (Storable a, Storable b) => a -> b
>> castAny = unsafePerformIO . genericCast
>> where
>> genericCast :: (Storable a, Storable b) => a -> IO b
>> genericCast v = return undefined >>= \r ->
>> allocaBytes (max (sizeOf v) (sizeOf r)) $ \p ->
>> poke p v >> if False then return r else peek (castPtr p)

>> > let a = -1000 :: Int16


>> > castAny a :: Word16 -->
>> 64536
>> > castAny a :: Ptr ()
>> 0xb4c2fc18

> Try it on a big endian architecture, or one that has alignment


> restrictions, or a different size for HsChar or so forth. Casting by
> 'punning' (as the C folks like to call it) does have uses, but they are
> generally hardware dependent and useful only in certain rare
> circumstances that a generic cast probably isn't likely to fill.

Do you think this could be used as a way to handle
C unions? If I had something like

union example {
struct firstview {
char c;
int n;
} fv;
long double ld;
};

and 'firstview' had been mapped in Haskell as, say,

FirstView {firstViewC :: CChar, firstVewN :: CInt}

I could check what I would get after pokeing values
using:

(firstViewN . unionCast) (pi :: CDouble)

Note that I changed the name from castAny to unionCast
to reflect its use.

Thanks for your comments,
Maur�cio

0 new messages