[Haskell-cafe] Re: [Haskell-beginners] Just how unsafe is unsafe
Thomas Davie
tom.davie at gmail.com
Fri Feb 6 02:08:54 EST 2009
On 5 Feb 2009, at 22:11, Andrew Wagner wrote:
> So we all know the age-old rule of thumb, that unsafeXXX is simply
> evil and anybody that uses it should be shot (except when it's ok).
>
> I understand that unsafeXXX allows impurity, which defiles our
> ability to reason logically about haskell programs like we would
> like to. My question is, to what extent is this true?
>
> Suppose we had a module, UnsafeRandoms, which had a function that
> would allow you to generate a different random number every time you
> call it. The semantics are relatively well-defined, impurity is
> safely sectioned off in its own impure module, which is clearly
> labeled as such. How much damage does this do?
The problem here is composability – you have no idea how far your non
referentially transparent code has spread, because you can compose
functions together willy nilly, meaning your random numbers can get
pushed through all sorts of things, and cause odd behaviors (e.g. if a
constant happens to get evaluated twice rather than once, and return
different values each time).
> Can we push the lines elsewhere? Is sectioning unsafeXXX into Unsafe
> modules a useful idiom that we can use for other things as well?
Well not useful modules, but useful types instead. The point of IO
for example is to deliberately construct an environment in which you
can't get one of your unsafe values out into the referentially
transparent world – the IO type denotes the line on which one side
contains unsafe values, and the other side does not.
There are however some instances where unsafe functions *are* safe,
Conal's unamb function for example, always returns the same value (as
long as its precondition is met), even though it contains IO based
code to race the values.
There are also some instances where unsafe functions are safe purely
through force of will. For example:
type ResourcePath = FilePath
loadImageResource :: ResourcePath -> Image
loadImageResource = unsafePerformIO . loadImage =<< readFile
This is safe iff you treat the resource as a part of your program,
just like your program's code, if it changes, the world falls down,
but as long as it's still there and still the same, you're entirely
safe.
Bob
More information about the Haskell-Cafe
mailing list