In Haskell, the base libraries and Hackage packages provide several means of converting binary IEEE-754 floating point data to and from the l
Simon Marlow mentions another approach in GHC bug 2209 (also linked to from Bryan O'Sullivan's answer)
You can achieve the desired effect using castSTUArray, incidentally (this is the way we do it in GHC).
I've used this option in some of my libraries in order to avoid the unsafePerformIO required for the FFI marshalling method.
{-# LANGUAGE FlexibleContexts #-}
import Data.Word (Word32, Word64)
import Data.Array.ST (newArray, castSTUArray, readArray, MArray, STUArray)
import GHC.ST (runST, ST)
wordToFloat :: Word32 -> Float
wordToFloat x = runST (cast x)
floatToWord :: Float -> Word32
floatToWord x = runST (cast x)
wordToDouble :: Word64 -> Double
wordToDouble x = runST (cast x)
doubleToWord :: Double -> Word64
doubleToWord x = runST (cast x)
{-# INLINE cast #-}
cast :: (MArray (STUArray s) a (ST s),
MArray (STUArray s) b (ST s)) => a -> ST s b
cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
I inlined the cast function because doing so causes GHC to generate much tighter core. After inlining, wordToFloat is translated to a call to runSTRep and three primops (newByteArray#, writeWord32Array#, readFloatArray#).
I'm not sure what performance is like compared to the FFI marshalling method, but just for fun I compared the core generated by both options.
Doing FFI marshalling is a fair bit more complicated in this regard. It calls unsafeDupablePerformIO and 7 primops (noDuplicate#, newAlignedPinnedByteArray#, unsafeFreezeByteArray#, byteArrayContents#, writeWord32OffAddr#, readFloatOffAddr#, touch#).
I've only just started learning how to analyse core, perhaps someone with more experience can comment on the cost of these operations?