[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 Beginners mailing list