
In another thread, I wrote:
main = (>> return ()) $ runListT $ do arg <- ListT getArgs n <- ListT $ return [1..3] liftIO $ putStrLn ((show n) ++ ") " ++ arg)
The frequent occurence of "ListT $ return" in my code when I use the ListT monad transformer has made me wonder why there isn't a standard typeclass `MonadList', like those for the other monad transformers, encapsulating the essence of being a "list-like" monad -- in this case, the ability to select from a list of things. I quickly wrote one for myself: class MonadList m where option :: [a] -> m a instance MonadList [] where option = id instance (Monad m) => MonadList (ListT m) where option = ListT . return Has anyone else thought about or done something like this? Mike

Michael Shulman wrote:
class MonadList m where option :: [a] -> m a
[...] There's no need for an extra class, it can be done with MonadPlus: option :: MonadPlus m => [a] -> m a option = msum . map return This definition came up before, for example here: http://www.haskell.org/haskellwiki/Sudoku enjoy, Bertram

On 9/13/06, Bertram Felgenhauer
Michael Shulman wrote:
class MonadList m where option :: [a] -> m a
[...]
There's no need for an extra class, it can be done with MonadPlus:
option :: MonadPlus m => [a] -> m a option = msum . map return
But this doesn't always give the behavior I want. It works for any monad of the form (ListT m), but not for a monad like (ErrorT e []). I would want runErrorT $ do x <- option [1..3] return x to return [Right 1, Right 2, Right 3], but with your definition it returns [Right 1]. This is because (ErrorT e []) inherits its instance of MonadPlus from Error, not from []. (Is there a reason for this, or is it just assumed that this is the more frequently desired behavior?) However, I declare instance (Error e) => MonadList (ErrorT e []) where option = lift then the above code does return [Right 1, Right 2, Right 3]. Mike

Michael Shulman wrote:
This is because (ErrorT e []) inherits its instance of MonadPlus from Error, not from []. (Is there a reason for this, or is it just assumed that this is the more frequently desired behavior?)
It's a flaw in MonadPlus, since it allows two different behaviours and really should be two different classes. See http://haskell.org/haskellwiki/MonadPlus. -- Ashley Yakeley

On 9/19/06, Ashley Yakeley
It's a flaw in MonadPlus, since it allows two different behaviours and really should be two different classes. See http://haskell.org/haskellwiki/MonadPlus.
Ah, excellent. So it sounds like at least in Haskell prime, I'll probably be able to use MonadPlus to do what I want, because MaybeT and ErrorT will be instances of MonadOr instead. Mike

Michael Shulman wrote:
The frequent occurence of "ListT $ return" in my code when I use the ListT monad transformer has made me wonder why there isn't a standard typeclass `MonadList', like those for the other monad transformers, encapsulating the essence of being a "list-like" monad -- in this case, the ability to select from a list of things. I quickly wrote one for myself:
class MonadList m where option :: [a] -> m a
Another use for this class is for selecting a random option:
instance MonadList SomeMonadWithRandomness where option os = pos <- randomRM (0, length os - 1) return (os !! pos)
It can also be used for the Nondet monad described in http://haskell.org/hawiki/NonDeterminism, and as a replacement for the Parsec combinator 'choice' (which IMHO is a better name). Although msum might suffice in these cases. Twan
participants (4)
-
Ashley Yakeley
-
Bertram Felgenhauer
-
Michael Shulman
-
Twan van Laarhoven