Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Simon Marlow mentions another approach in <a href="http://hackage.haskell.org/trac/ghc/ticket/2209">GHC bug 2209</a> (also linked to from Bryan O'Sullivan's answer)</p> <blockquote> <p>You can achieve the desired effect using castSTUArray, incidentally (this is the way we do it in GHC).</p> </blockquote> <p>I've used this option in some of my libraries in order to avoid the <code>unsafePerformIO</code> required for the FFI marshalling method.</p> <pre><code>{-# LANGUAGE FlexibleContexts #-} import Data.Word (Word32, Word64) import Data.Array.ST (newArray, castSTUArray, readArray, MArray, STUArray) import GHC.ST (runST, ST) wordToFloat :: Word32 -&gt; Float wordToFloat x = runST (cast x) floatToWord :: Float -&gt; Word32 floatToWord x = runST (cast x) wordToDouble :: Word64 -&gt; Double wordToDouble x = runST (cast x) doubleToWord :: Double -&gt; Word64 doubleToWord x = runST (cast x) {-# INLINE cast #-} cast :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) =&gt; a -&gt; ST s b cast x = newArray (0 :: Int, 0) x &gt;&gt;= castSTUArray &gt;&gt;= flip readArray 0 </code></pre> <p>I inlined the cast function because doing so causes GHC to generate much tighter core. After inlining, <code>wordToFloat</code> is translated to a call to <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/GHC-ST.html#runSTRep">runSTRep</a> and three <a href="http://www.haskell.org/ghc/docs/7.0.4/html/libraries/ghc-prim-0.2.0.0/GHC-Prim.html">primops</a> (<code>newByteArray#</code>, <code>writeWord32Array#</code>, <code>readFloatArray#</code>).</p> <p>I'm not sure what performance is like compared to the FFI marshalling method, but just for fun I compared the core <a href="https://gist.github.com/1135110">generated by both options</a>.</p> <p>Doing FFI marshalling is a fair bit more complicated in this regard. It calls <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/GHC-IO.html#unsafeDupablePerformIO">unsafeDupablePerformIO</a> and 7 primops (<code>noDuplicate#</code>, <code>newAlignedPinnedByteArray#</code>, <code>unsafeFreezeByteArray#</code>, <code>byteArrayContents#</code>, <code>writeWord32OffAddr#</code>, <code>readFloatOffAddr#</code>, <code>touch#</code>).</p> <p>I've only just started learning how to analyse core, perhaps someone with more experience can comment on the cost of these operations?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload