Skip to content

Instantly share code, notes, and snippets.

@Mercerenies
Created January 27, 2018 17:02
Show Gist options
  • Save Mercerenies/7aad5e60e81dd97e3c0a0cfc1fc03702 to your computer and use it in GitHub Desktop.
Save Mercerenies/7aad5e60e81dd97e3c0a0cfc1fc03702 to your computer and use it in GitHub Desktop.
A monad transformer based on `NonEmptyT`
-- Note: The same warnings about ListT's poor behavior apply to this transformer.
-- https://wiki.haskell.org/ListT_done_right
import Data.List.NonEmpty
import Control.Monad
import Control.Monad.List
newtype NonEmptyT m a = NonEmptyT { unNonEmptyT :: m (NonEmpty a) }
instance Functor m => Functor (NonEmptyT m) where
fmap f (NonEmptyT xx) = NonEmptyT $ fmap (fmap f) xx
instance Applicative m => Applicative (NonEmptyT m) where
pure x = NonEmptyT $ pure (x :| [])
(NonEmptyT ff) <*> (NonEmptyT xx) = NonEmptyT $ (<*>) <$> ff <*> xx
instance Monad m => Monad (NonEmptyT m) where
return = pure
(NonEmptyT xx) >>= ff = NonEmptyT $ do
xs <- xx
ys <- mapM (unNonEmptyT . ff) xs
return $ join ys
instance MonadTrans NonEmptyT where
lift m = NonEmptyT $ fmap (\x -> x :| []) m
testList :: ListT Maybe a -> ListT Maybe a
testList (ListT (Just [])) = ListT Nothing
testList x = x
testList' :: [a] -> NonEmptyT Maybe a
testList' [] = NonEmptyT Nothing
testList' (x:xs) = NonEmptyT $ Just (x :| xs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment