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.)