
Hi Pietro, The reply I wrote yesterday was sent when I ran out of time, but I have since realized that I failed to get to the point. Sorry about that! The demo shows that you can use `hashPassword` with `IO` and `ByteString`, as if the type was the following: hashPassword :: Int -> ByteString -> IO ByteString The use of type classes allows the function to be used with other types as well, however. This makes the function more flexible for different people's needs. For example, a project may use this function in a user registration request handler. Perhaps that request handler needs to write to a database as well as perform logging. It can be implemented using a monad that has the context required for these features, so that the it can do all of these things without being concerned with configuration details. The monad may have the following constraints: * `MonadRandom m` so that `hashPassword` can be used * `MonadLogger m` so that it can log in the configured way * `MonadDatabase m` (using some application-defined monad) so that it has access to the application database If `hashPassword` had the above `IO` type, then it would not work in such an application monad directly. If there is a `MonadIO` instance, then one could use `liftIO`, but some application monads specifically do *not* have `MonadIO` instances to make it more difficult to simply run things in `IO`. I am out of time again, but I hope this two-part reply is helpful. Cheers, Travis