I am currently writing a project where I make a heavy use of ListT
monad transformer. When using plain lists, implementing nondeterminism is very easy. However once I had to convert my code to ListT
, it got much more complicated 1.
As a simple example: converting from [a]
to ListT a
actually requires composing two functions:
conv :: (Monad m) => [a] -> ListT m a
conv = ListT . return
Though it's simple, I am surprised it's not already there.
Questions:
ListT
?1 The exact reasons are quite complicated, so I don't really want to elaborate too much on that.
I don't think there are any libraries for this; conv
is an incredibly simple function, after all, and the other way around is just runListT
.
conv
is similar to the liftMaybe
often desired when using MaybeT
:
liftMaybe :: (Monad m) => Maybe a -> MaybeT m a
liftMaybe = MaybeT . return
I would recommend naming it something along the lines of liftList
.1
As far as a better monad transformer for nondeterminism goes, I recommend taking a look at the logict package, based on Oleg's LogicT
transformer, which is a continuation-based backtracking logic monad with some helpful operations. As a bonus, since []
is an instance of MonadLogic
, those operations also work on lists.
1 Interestingly, we can define a function that generalises the pattern of conv
and liftMaybe
:
import Data.Foldable (Foldable)
import qualified Data.Foldable as F
choose :: (Foldable t, MonadPlus m) => t a -> m a
choose = F.foldr (\a b -> return a `mplus` b) mzero
This will probably make your code quite confusing, so I don't recommend using it :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With