
I'm implementing the low-level interface to a large C library (using c2hs). The C functions can be broadly classified by: *) the main datastructure they operate on, e.g. returnType AFunction (A* a, ...); *) creation, modification, read access, destruction operations for each of these datastructures, following a common pattern: ACreate(), ASet1(), ASet2(), .., ARead(), ADestroy(), BCreate(), etc. The library rests on top of MPI, so there are e.g. AScatterBegin(), AScatterEnd() function pairs that account for potentially large delays associated with computing and moving data around. On the Haskell side, the C pointer types are represented as e.g. data Ah = Ah (Ptr Ah) deriving instance Storable Ah and e.g. a Create function returns the representation of the fresh pointer along with the usual integer error code: ahCreate :: MPIComm -> IO (Ah, Err) What abstraction may I use to capture logic such as: *) separate read-only functions from the potentially overwriting ones *) guarantee precedence relations (e.g. computation can only occur after initialization) *) collect or even compose error codes, letting computation go through iff Err==0 (e.g. a n-ary Maybe ?) Sequencing in the IO monad causes all effectful functions to run and return their result and/or error code. All feedback is welcome; Thank you in advance

I meant
newtype Ah = Ah (Ptr Ah)
not
data Ah = Ah (Ptr Ah)
Thanks
On 21 May 2015 at 06:20, Marco Zocca
I'm implementing the low-level interface to a large C library (using c2hs).
The C functions can be broadly classified by: *) the main datastructure they operate on, e.g. returnType AFunction (A* a, ...); *) creation, modification, read access, destruction operations for each of these datastructures, following a common pattern: ACreate(), ASet1(), ASet2(), .., ARead(), ADestroy(), BCreate(), etc.
The library rests on top of MPI, so there are e.g. AScatterBegin(), AScatterEnd() function pairs that account for potentially large delays associated with computing and moving data around.
On the Haskell side, the C pointer types are represented as e.g. data Ah = Ah (Ptr Ah) deriving instance Storable Ah
and e.g. a Create function returns the representation of the fresh pointer along with the usual integer error code: ahCreate :: MPIComm -> IO (Ah, Err)
What abstraction may I use to capture logic such as: *) separate read-only functions from the potentially overwriting ones *) guarantee precedence relations (e.g. computation can only occur after initialization) *) collect or even compose error codes, letting computation go through iff Err==0 (e.g. a n-ary Maybe ?) Sequencing in the IO monad causes all effectful functions to run and return their result and/or error code.
All feedback is welcome; Thank you in advance
participants (1)
-
Marco Zocca