haskellffiunsafe-perform-io

Immutable data from FFI and unsafePerformIO


I'm doing a Haskell binding to an image loading library and I want to avoid copying as much as possible. When an image is loaded, I get back a data structure from the C library containing the image data. Now, this structure is for all intents and purposes immutable but to read the data from it into Haskell is an IO action. Would it be okay to use unsafePerformIO (or perhaps unsafeDupablePerformIO for even better performance) to avoid copying the memory into a Haskell array or similar? Of course, I would need to encapsulate the data structure pointer in a ForeignPtr or similar and ensure that the pointer cannot be accessed or modified in any other way.

What's the convention in cases such as these?


Solution

  • if the data is truely immutable logically, then unsafePerformIO or FFI importing as a pure function is okay. unsafePerformIO is not inherently bad, it just shifts the burden of proof from the compiler to you as to whether an operation is referentially transparent. Now, this is actually something tricky and non obvious to prove sometimes, so you are introducing an opprotunity for a big bug that is very difficult to track down, NEVER assume that just because you can't think of a bug with pretending something is referentially transparent but isn't means it is okay. The compiler is very very clever about exploiting opprotunities to optimize things. So make sure you are actually proving immutable referential transparency and not just convincing yourself that you can't think of a way it can go wrong. But if your proof is solid, then you should not feel guilty for using it.

    Note that this could have consequences when it comes to memory consumption, immutable values can stick around in unevaluated thunks and since the haskell compiler only knows your object through a ForeginPtr it has no idea how expensive it is to retain, so logical immutability may not be enough if your immutable object is large enough that the explicit lifetime aspects of using the IO monad is useful to you. the type system guarentees correctness, efficiency is another matter.