A few days ago I was trying to prove monad laws by creating a new monad instance but I found myself stuck at defining the new monad instance.
{-# LANGUAGE DeriveFunctor, InstanceSigs #-}
import Control.Monad
newtype Test a = Test { getTest :: [Maybe a] }
deriving Functor
instance Applicative Test where
pure = return
(<*>) = liftM2 ($)
instance Monad Test where
return :: a -> Test a
return a = Test $ [Just a]
(>>=) :: Test a -> (a -> Test b) -> Test b
g >>= f = concat (map f g) --Tried to do something like this
I tried something following the list monad definition, but is stuck because concat expects [[a]] but here it gets [Test b], so maybe there are other functions available or is there a way to make concat work on the newType? Any suggestions are appreciated. Thanks.
Unlike
type
aliases,newtype
wrappers need to be manually applied and removed. Replaceg >>= f = concat (map f g)
withTest g >>= f = Test $ concat (map (getTest . f) g)
.This will leave you with only one more type error:
g
has type[Maybe a]
instead of the needed[a]
. We can tack on acatMaybes
(needsimport Data.Maybe
) to take care of that:Test g >>= f = Test $ concat (map (getTest . f) $ catMaybes g)
. Now it compiles.Unfortunately, this instance isn't lawful. I'll leave it as an exercise for the reader to establish why not, and whether it can be easily fixed.