来自FFI和unsafePerformIO的不可变数据

时间:2014-02-23 11:17:03

标签: haskell ffi unsafe-perform-io

我正在对图像加载库进行Haskell绑定,我希望尽可能避免复制。加载图像时,我从包含图像数据的C库中获取数据结构。现在,这个结构对于所有意图和目的都是不可变的,但是将数据从它读入Haskell是一个IO动作。是否可以使用unsafePerformIO(或者也许是unsafeDupablePerformIO以获得更好的性能)来避免将内存复制到Haskell数组或类似内容中?当然,我需要将数据结构指针封装在ForeignPtr或类似的中,并确保不能以任何其他方式访问或修改指针。

这些案件的惯例是什么?

1 个答案:

答案 0 :(得分:9)

如果数据在逻辑上是真正不可变的,那么unsafePerformIO或FFI作为纯函数导入是可以的。 unsafePerformIO本质上不是坏事,它只是将证据负担从编译器转移给你,看看操作是否是引用透明的。现在,这实际上有些棘手而且不明显有时候证明,所以你正在为一个很难追查的大错误引入一个机会,从不认为只是因为你不能想到假装某些东西是错误的错误透明,但不是意味着它没关系。编译器非常聪明地利用opprotunities来优化事物。因此,请确保您实际上证明了不可变的引用透明度,而不仅仅是说服自己不能想到它可能出错的方式。但如果你的证据是可靠的,那么你就不应该为使用它而感到内疚。

请注意,这可能会对内存消耗产生影响,不可变值可以在未评估的thunk中保留,并且由于haskell编译器只通过ForeginPtr知道您的对象,因此它不知道保留的成本是多少,因此逻辑不变性如果你的不可变对象足够大,使用IO monad的显式生命周期方面对你有用,可能还不够。类型系统保证了正确性,效率是另一回事。