
Hello all, I'm trying to make an IMAP DSL and I'm face to an annoying issue (all the examples after are selected pieces of this: https://github.com/blackheaven/smoothmail). Here we are, IMAP provide a way to statefully interact with a server. For example: select "A" -- Select folder 'A' searchAll -- Get the list of UID (message identifiers) [1, 2, 3] But select "B" searchAll -- Get [4, 5] I decided to use the Free Monad because it seems well suite for what I'm doing and I end-up with something like that: data ImapF next = Select DirectoryName (Maybe DirectoryDescription -> next) | Noop (DirectoryDescription -> next) | Search MailSearch (Maybe [UID] -> next) -- Functor instance type Imap = Free ImapF searchAll :: Imap (Maybe [UID]) searchAll = liftF $ Search undefined id select :: DirectoryName -> Imap (Maybe DirectoryDescription) select directory = liftF $ Select directory id My main problem is the following: if I do a select of an unknown directory, I should stop the computation. My first thought was Monad Transformers. So here are the types: newtype FreeT f m a = FreeT { runFreeT :: m (FreeF f a (FreeT f m a)) } Such that f is a functor and m a monad. If I do a type Imap = FreeT ImapF Maybe I'll end up with some Maybe (ImapF a) which not expresses that the evaluation can fails but that the expression construction can fails. Then I thought harder and ends up with that: type Imap = FreeT Maybe (Free ImapF) Ok, that seems better, but all the available operations can't fail. I also have had a look at extensible effects and I think I'm stuck with the same issue of my first attempt. My goal is to provide flexibility for those who want to continue the evaluation, but to provide an API with less boilerplate in the default case. If you have any ideas/hints/comments, I'll be happy to read them. If you have any questions, I'll do my best to answer them and to make disappear all doubt and ambiguity. Thanks in advance for your help. Regards.