error in your article? about meaning of safe/unsafe in "foreign import"

Peter Simons simons at cryp.to
Fri May 20 05:30:08 EDT 2005


Bulat,

just for the record, it's not my article. Although I have the
privilege of sharing a somewhat similar name with the geniuses
around here, I didn't have any part in that text. ;-)

You were wondering about this declaration:

 >  foreign import ccall unsafe sin :: Float -> Float

I guess you are confused by the difference between safe/unsafe
FFI calls versus pure/impure FFI calls. Which is comforting
for me, because as it happens I don't quite understand that
either. ;-) I'll try to explain what I believe I do
understand, and hope that the others on this list chime in
case I mess something up.

A pure function is one without side-effects, meaning that the
result depends only on the function arguments. Those are
surprisingly few; the C function strlen(3) for example is
_not_ pure because it depends on the fact that the memory
pointed to by the argument actually contains the string
which's length you'd like to compute. So the strlen() call
must occur in the correct order in relation to other I/O calls
like as read(), malloc(), or whatever. Thus, the signature for
strlen() would be:

    strlen :: Ptr CChar -> IO CSize

The sin(3) function on the other hand is pure. It doesn't
depend on anything but the floating point value you give it,
hence in can be evaluated at any point of the program
execution, hence it doesn't need to be in the IO monad:

    sin :: CFloat -> CFloat

Now, safe and unsafe calls are a different beast:

 | A safe call is less efficient, but guarantees to leave the
 | Haskell system in a state that allows callbacks from the
 | external code. In contrast, an unsafe call, while carrying
 | less overhead, must not trigger a callback into the Haskell
 | system.

The vast majority of C function you will call are unaware of
Haskell. They will not trigger anything the Haskell runtime
system needs to know about, nor will they force a part of your
Haskell program to be evaluated. Those functions can be called
unsafely, just like the definition above says.

Since pure FFI calls don't have any side-effects, they are
always safe to be called unsafely. (Yes, the choice of the
words "safe" and "unsafe" is a bit unfortunate in the standard
here.) So unless I am very mistaken, the declaration

  foreign import ccall safe sin :: Float -> Float

would work just as well as the one above does, but it would be
less efficient.

In other words, if you declare a FFI function to be called
safely, and to be called from within the IO monad, then
absolutely nothing can possibly go wrong. ;-)


 > is it possible to download sources of http server mentioned
 > in this article?

I think the (more or less) latest version is here:

  http://www.mdstud.chalmers.se/~md9ms/hws-wp/

Another somewhat extensive example for system programming in
Haskell is available here:

  http://postmaster.cryp.to/

Hope this helps.

Peter



More information about the Glasgow-haskell-users mailing list