[Haskell-cafe] Re: Is it safe to use unsafePerformIO here?

Cristiano Paris frodo at theshire.org
Sun Sep 20 05:35:47 EDT 2009


On Sat, Sep 19, 2009 at 6:53 PM, Ben Franksen <ben.franksen at online.de> wrote:
> Cristiano Paris wrote:
>> Daniel Fischer wrote:
>>> I would separate the reading of headers and bodies, reopening the files
>>> whose body is needed, for some (maybe compelling) reason he wants to do
>>> it differently.
>>
>> Yes, that's the way Haskell forces you to do that as it's the only way
>> for you to go safe.
>
> I don't think it has anything to do with Haskell.

My sentence was to be understood in a positive way. I think this has a
lot to do with Haskell, as it forbids you to write certain kinds of
programs: this is a distinguished feature of all the static typed
languages and more specifically in Haskell, which has a very
expressive type system. In particular, you can't have a program that
runs IO "out-of-order": if you really want to do that, you must use
unsafe(Perform|Interleave)IO which is like cheating, in a way.

Indeed, the only way to do that not using unsafePerformIO is to have a
two stage reading, either making the body an IO action or having an
intermediate data structure which represents a file whose body has not
been read yet: in general this is safer, unless you know something
about your program and can assure the compiler it won't behave badly
with respect to side effects.

> How would you do this in
> C? You'd pass a flag indicating whether to read the whole file or just the
> header. You can do the same in Haskell, of course, no lazy IO needed. The
> body remains undefined if the flag indicates header only. Even better wrap
> the body in a Maybe.

The difference is in the expressivity of the type system.

In C I may use a NULL pointer indicating the body has not been read
yet, but then the compiler won't enforce good uses of that pointer and
can't assure you that in no way a NULL pointer would be ever
dereferenced, leaving room for untested, uncaught bugs.

In Haskell this is simply not possible.

>...
> I have a hard time believing this is possible, if you demand that the files
> should not stay opened indefinitely. How is the runtime supposed to know
> whether to close the file or not? What you /can/ do is use unsafePerformIO
> to lazily re-open, read the body, and close the file, as soon as the body
> gets demanded. However, this is ugly and not advised.

Here in Cafè once I had a discussion about when is safe and advisable
to use unsafePerformIO. I don't think this function is evil per-se and
indeed THERE ARE situations where it's more elegant and clear
implementing things using unsafePerformIO. I see it as way to tell the
compiler "don't mind: I know what I'm doing". This is certainly true
when using FFI to implement in C pure functions, but it's true in
other situations, like mine, in which using unsafeInterleaveIO allows
me to write my code cleanly and easily, separating IO from processing,
and avoid having to read the files in a two-stage way.

Of course, I can be wrong and I can't look forward to hearing from the
wise people and argument againts my point.

> Cheers
> Ben

Thanks.

Cristiano


More information about the Haskell-Cafe mailing list