
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.

On Sat, Jan 24, 2015 at 07:46:52PM +0100, Gautier DI FOLCO wrote:
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.
What do you mean you "should stop the computation"? Do you mean the interpretation of the free monad should be forced to stop? If so, doesn't making the type of the `Select` constructor Select DirectoryName (DirectoryDescription -> next) achieve this? That way if the interpreter talks issues a select command to the server and fails to receive a `DirectoryDescription` in return then it is forced to stop. Tom

2015-01-25 9:37 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
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
On Sat, Jan 24, 2015 at 07:46:52PM +0100, Gautier DI FOLCO wrote: directory,
I should stop the computation.
What do you mean you "should stop the computation"? Do you mean the interpretation of the free monad should be forced to stop? If so, doesn't making the type of the `Select` constructor
Select DirectoryName (DirectoryDescription -> next)
achieve this? That way if the interpreter talks issues a select command to the server and fails to receive a `DirectoryDescription` in return then it is forced to stop.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Hello, Thanks for your answer. If I do it this way, the evaluation is forced to be stopped, I have no way to react to this error.

On Sun, Jan 25, 2015 at 10:39:48PM +0100, Gautier DI FOLCO wrote:
2015-01-25 9:37 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
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
On Sat, Jan 24, 2015 at 07:46:52PM +0100, Gautier DI FOLCO wrote: directory,
I should stop the computation.
What do you mean you "should stop the computation"? Do you mean the interpretation of the free monad should be forced to stop? If so, doesn't making the type of the `Select` constructor
Select DirectoryName (DirectoryDescription -> next)
achieve this? That way if the interpreter talks issues a select command to the server and fails to receive a `DirectoryDescription` in return then it is forced to stop.
If I do it this way, the evaluation is forced to be stopped, I have no way to react to this error.
Could you explain more precisely what you are trying to achieve, perhaps with an example? Tom

2015-01-25 22:47 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
2015-01-25 9:37 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
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
On Sat, Jan 24, 2015 at 07:46:52PM +0100, Gautier DI FOLCO wrote: directory,
I should stop the computation.
What do you mean you "should stop the computation"? Do you mean the interpretation of the free monad should be forced to stop? If so, doesn't making the type of the `Select` constructor
Select DirectoryName (DirectoryDescription -> next)
achieve this? That way if the interpreter talks issues a select command to the server and fails to receive a `DirectoryDescription` in return
On Sun, Jan 25, 2015 at 10:39:48PM +0100, Gautier DI FOLCO wrote: then it
is forced to stop.
If I do it this way, the evaluation is forced to be stopped, I have no way to react to this error.
Could you explain more precisely what you are trying to achieve, perhaps with an example?
Tom _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
In fact I'm looking for a practical way to alter Imap to change it temporarily or not, globally or locally in a failable monad. Example: select "Unknown" -- will fail doSomethingUnrelated failableLessMode select "Unknown" -- will fail doSomethingUnrelated -- unreached expression -- or select "Unknown" $ do-- will fail doSomethingUnrelated -- unreached expression where :: Imap (Maybe a) -> (a -> Imap b) -> Imap (Maybe b) Is it clearer? Please let me know. Thanks.

On Sun, Jan 25, 2015 at 11:29:27PM +0100, Gautier DI FOLCO wrote:
2015-01-25 22:47 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
On Sun, Jan 25, 2015 at 10:39:48PM +0100, Gautier DI FOLCO wrote:
2015-01-25 9:37 GMT+01:00 Tom Ellis < tom-lists-haskell-cafe-2013@jaguarpaw.co.uk>:
On Sat, Jan 24, 2015 at 07:46:52PM +0100, Gautier DI FOLCO wrote:
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.
What do you mean you "should stop the computation"? Do you mean the interpretation of the free monad should be forced to stop? If so, doesn't making the type of the `Select` constructor
Select DirectoryName (DirectoryDescription -> next)
achieve this? That way if the interpreter talks issues a select command to the server and fails to receive a `DirectoryDescription` in return then it is forced to stop.
If I do it this way, the evaluation is forced to be stopped, I have no way to react to this error.
Could you explain more precisely what you are trying to achieve, perhaps with an example?
In fact I'm looking for a practical way to alter Imap to change it temporarily or not, globally or locally in a failable monad.
Example:
select "Unknown" -- will fail doSomethingUnrelated
failableLessMode select "Unknown" -- will fail doSomethingUnrelated -- unreached expression -- or select "Unknown" $ do-- will fail doSomethingUnrelated -- unreached expression
where :: Imap (Maybe a) -> (a -> Imap b) -> Imap (Maybe b)
It's still not completely clear. A you looking for an implementation of ? That is essentially just MaybeT and exists for any monad: () :: (Functor m, Monad m) => m (Maybe a) -> (a -> m b) -> m (Maybe b) m f = m >>= (\x -> case x of Nothing -> return Nothing Just a -> fmap Just (f a))
participants (2)
-
Gautier DI FOLCO
-
Tom Ellis