haskell - How to create two ByteStrings calling this external library API? -


i'm writing bindings cryptographic library exposes function generating keypairs:

const size_t publickeybytes = 32; const size_t secretkeybytes = 32; int random_keypair(unsigned char pk[publickeybytes],                    unsigned char sk[secretkeybytes]); 

this function randomly generates secret key, computes corresponding public key , puts results in pk , sk.

when returning 1 bytestring i've found easiest way use create :: int -> (ptr word8 -> io ()) -> io bytestring data.bytestring.internal. however, function can't create 2 bytestrings @ same time.

my first approach write like:

newtype publickey = publickey bytestring newtype secretkey = secretkey bytestring randomkeypair :: io (publickey, secretkey) randomkeypair =     let pk = b.replicate 0 publickeybytes         sk = b.replicate 0 secretkeybytes     b.unsafeuseascstring pk $ \ppk ->         b.unsafeuseascstring sk $ \psk ->         c_random_keypair ppk psk     return (publickey pk, secretkey sk) 

however, doesn't seem work ghc 7.10.2. when running test suite i'm finding seem have sharing of bytestrings in between function calls, leading encryption/decryption failing , giving incorrect results.

i've managed work around problem defining own function:

createwithresult :: int -> (ptr word8 -> io a) -> io (bytestring, a) createwithresult f =     fp <- b.mallocbytestring     r <- withforeignptr fp f     return (b.fromforeignptr fp 0 i, r) 

and using like:

randomkeypair = fmap (publickey *** secretkey) $     createwithresult publickeybytes $ \ppk ->     b.create secretkeybytes $ \psk ->     void $ c_random_keypair ppk psk 

this seems work, tests pass.

my question is, semantics when comes sharing , referential transparency when comes io monad?

my intuition told me (incorrectly) solve problem in first way, apparently couldn't. believe happening optimizer saw let-statements floated top level definitions, , reason got these issues.

the problem first approach you're trying modify immutable value (pk , sk in function). docs unsafeuseascstring say:

modifying cstring, either in c, or using poke, cause contents of bytestring change, breaking referential transparency

the io monad doesn't have different semantics when comes sharing , referential transparency. in fact, let in do block not in way related io monad; code equivalent to:

randomkeypair :: io (publickey, secretkey) randomkeypair =     let pk = b.replicate 0 publickeybytes         sk = b.replicate 0 secretkeybytes     in b.unsafeuseascstring pk (\ppk ->         b.unsafeuseascstring sk $ \psk ->         c_random_keypair ppk psk) >>     return (publickey pk, secretkey sk) 

now it's visible pk , sk can floated top level.


Comments

Popular posts from this blog

python - ValueError: empty vocabulary; perhaps the documents only contain stop words -

java - UnknownEntityTypeException: Unable to locate persister (Hibernate 5.0) -

ubuntu - collect2: fatal error: ld terminated with signal 9 [Killed] -