The `_ccall_' construct is part of the `PrimIO' monad because 9 out of 10 uses will be to call imperative functions with side effects such as `printf'. Use of the monad ensures that these operations happen in a predictable order in spite of laziness and compiler optimisations.
There are three situations where one might like to use `unsafePerformPrimIO' to avoid the monad:
atan2d :: Double -> Double -> Double
atan2d y x = unsafePerformPrimIO (_ccall_ atan2d y x)
sincosd :: Double -> (Double, Double)
sincosd x = unsafePerformPrimIO (
newDoubleArray (0, 1) `thenPrimIO` \ da ->
_casm_ "sincosd( %0, &((double *)%1[0]), &((double *)%1[1]) );" x da
`seqPrimIO`
readDoubleArray da 0 `thenPrimIO` \ s ->
readDoubleArray da 1 `thenPrimIO` \ c ->
returnPrimIO (s, c)
)
empty :: EFS x
update :: EFS x -> Int -> x -> EFS x
lookup :: EFS a -> Int -> a
empty = unsafePerformPrimIO (_ccall_ emptyEFS)
update a i x = unsafePerformPrimIO (
makeStablePtr x `thenPrimIO` \ stable_x ->
_ccall_ updateEFS a i stable_x
)
lookup a i = unsafePerformPrimIO (
_ccall_ lookupEFS a i `thenPrimIO` \ stable_x ->
deRefStablePtr stable_x
)
You will almost always want to use `_MallocPtr's with this.
trace :: String -> a -> a
trace string expr = unsafePerformPrimIO (
appendChan# "stderr" "Trace On:\n" `seqPrimIO`
appendChan# "stderr" string `seqPrimIO`
appendChan# "stderr" "\nTrace Off.\n" `seqPrimIO`
returnPrimIO expr )
(This kind of use is not highly recommended -- it is only really
useful in debugging code.)