
If MR the more agreeable path then I'll do it, though this means I use the unholy "fail" function.
You don't want to use monads because the Monad class defines the fail function?
Sorry, I phrased this better on the blog comment. I don't want to use "MonadRandom m => m (p,p)" (MonadRandom + fail) instead of "Either GenError (B,ByteString, g)" because it limits my options for failure down to a piddly "fail :: String -> m a" (ignoring exceptions) - right now my options for failure are much richer, I can say ReseedRequred or NotEnoughEntropy etc, giving the user errors that can be handled by a simple pattern matching case expression.
In general, I like this approach, but what are encrypt privateKey or decrypt publicKey
supposed to do? A type-class solution also does not *prevent* programmers to perform such non-sensical calls
Would it be desirable to prohibit such calls using the type system?
As was earlier pointed out, these are actually valid operations for many public key systems. In fact, it's possible to use these for signing or verifying messages: Signing ==> encrypt privateKey . encode . hash Verifying signature ==> \sig msg -> decrypt publicKey sig == encode (hash msg) What makes a key public and another private is simply your pick of which to publish and which to protect as jealously as my daughter guards her cup of water (seriously, I can't get it from her). Cheers, Thomas