Use monad based error handling and move some stuff to internal modules.