
Dear Haskellers, I have a question about the FFI and interfacing to C++ via C. I want to use funcionality that I have implemented a while ago using C++ classes, and I also see this as an exercise on how to create wrappers using the Haskell FFI. The class I want to wrap first is a matrix class. Here is the thing: In order to create a matrix object, I create a C function that calls the C++ new operator, creating a matrix object, and returning it as a void pointer. Deletion is handled analogously. Then in Haskell, I import the two functions, and I have a matrix type like this: newtype Matrix = Matrix (Ptr Matrix) From this I create a ForeignPtr with newForeignPtr, giving the deletion function (which calls the C++ destructor for a matrix) as finalizer. Testing this showed me that it does work. /But/: So far everything is happening in the IO monad. However, I want to be able to work with matrices outside IO. Now, of course memory allocation can fail, and I don't want to use something like unsafePerformIO when there can actually be a failure when calling the constructor for a matrix. Is there a recommended way to do this? Also, is there a way to get memory from the Haskell runtime system in a safer way and construct the object in that memory? I hope I could make myself clear enough, as usual thanks for any hints!! Christian

Hello Christian, Assuming that the foreign library is based off of mutation on matrices, there's not an easy way to export a nice pure interface to them, because they're not actually persistent: if another thread goes and modifies some pointer which you also have in pure code, referential transparency is broken. So you'll have to think carefully about what sorts of guarantees you can (or want) to make to Haskell, and if you can't fulfill them, keep the code in IO (or create your own monad for manipulating matrices). Edward

Hi Edward, hello to all list members,
thank you for your comments, I will keep that in mind. There will be
operations on matrices (and other objects) which modify the objects,
and those will be in IO or ST, I think.
However, I am planning to provide operations with matrices which guarantee
that each involved matrix is not changed, but which may return new matrices.
All matrices have to be allocated, and that allocation can fail ... how does
one usually go about this problem in Haskell?
Cheers,
Christian
2011/2/9 Edward Z. Yang
Hello Christian,
Assuming that the foreign library is based off of mutation on matrices, there's not an easy way to export a nice pure interface to them, because they're not actually persistent: if another thread goes and modifies some pointer which you also have in pure code, referential transparency is broken. So you'll have to think carefully about what sorts of guarantees you can (or want) to make to Haskell, and if you can't fulfill them, keep the code in IO (or create your own monad for manipulating matrices).
Edward

On Wed, Feb 9, 2011 at 8:57 AM, C Gosch
Hi Edward, hello to all list members, thank you for your comments, I will keep that in mind. There will be operations on matrices (and other objects) which modify the objects, and those will be in IO or ST, I think. However, I am planning to provide operations with matrices which guarantee that each involved matrix is not changed, but which may return new matrices. All matrices have to be allocated, and that allocation can fail ... how does one usually go about this problem in Haskell? Cheers, Christian
I would check for allocation failure in the C wrapper and return a status code or error message back to Haskell. Thus the prototype of the C wrapper might be:
result_code_t c_create_matrix(t1 arg1, t2 arg2, c_matrix *result);
Then you could either throw a Haskell exception (which is allowed from pure code - but can only be caught in IO) or do everything under 'Maybe'. If you expect allocation failure to be rare and exceptional, I would lean towards the exception. I haven't had the occasion to wrap C libraries were I expected this sort of thing. Antoine
2011/2/9 Edward Z. Yang
Hello Christian,
Assuming that the foreign library is based off of mutation on matrices, there's not an easy way to export a nice pure interface to them, because they're not actually persistent: if another thread goes and modifies some pointer which you also have in pure code, referential transparency is broken. So you'll have to think carefully about what sorts of guarantees you can (or want) to make to Haskell, and if you can't fulfill them, keep the code in IO (or create your own monad for manipulating matrices).
Edward
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Thanks Antoine and Edward! I will try the exception in my first go. Christian On Wed, 2011-02-09 at 11:26 -0600, Antoine Latter wrote:
On Wed, Feb 9, 2011 at 8:57 AM, C Gosch
wrote: Hi Edward, hello to all list members, thank you for your comments, I will keep that in mind. There will be operations on matrices (and other objects) which modify the objects, and those will be in IO or ST, I think. However, I am planning to provide operations with matrices which guarantee that each involved matrix is not changed, but which may return new matrices. All matrices have to be allocated, and that allocation can fail ... how does one usually go about this problem in Haskell? Cheers, Christian
I would check for allocation failure in the C wrapper and return a status code or error message back to Haskell. Thus the prototype of the C wrapper might be:
result_code_t c_create_matrix(t1 arg1, t2 arg2, c_matrix *result);
Then you could either throw a Haskell exception (which is allowed from pure code - but can only be caught in IO) or do everything under 'Maybe'.
If you expect allocation failure to be rare and exceptional, I would lean towards the exception. I haven't had the occasion to wrap C libraries were I expected this sort of thing.
Antoine
2011/2/9 Edward Z. Yang
Hello Christian,
Assuming that the foreign library is based off of mutation on matrices, there's not an easy way to export a nice pure interface to them, because they're not actually persistent: if another thread goes and modifies some pointer which you also have in pure code, referential transparency is broken. So you'll have to think carefully about what sorts of guarantees you can (or want) to make to Haskell, and if you can't fulfill them, keep the code in IO (or create your own monad for manipulating matrices).
Edward
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (5)
-
.
-
Antoine Latter
-
C Gosch
-
ch.gosch@googlemail.com
-
Edward Z. Yang