Key idea
My understanding is that Missing3 and Unknown3 work a bit like Nothing, except they give a little more feedback about why there's no answer, so might behave slightly differently to each other. Certainly I think Missing3 should behave like Nothing.
Let's look at how these are defined for Maybe:
Functor
Here's the Functor instance for Maybe:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
I think it's clear how to deal with Missing3 and Unknown3 here.
Monad
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= _ = Nothing
(Just _) >> k = k
Nothing >> _ = Nothing
return = Just
fail _ = Nothing
You can't help but do the same here with >>= for Missing3 and Unknown3, since you don't have a value to bind with. The only question is do you fail with Unknown3 or Missing3?
Applicative
Here's where there's a little more digging:
instance Applicative Maybe where
pure = return
(<*>) = ap
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap = liftM2 id
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
Now that translates to
mf <*> mx = do
f <- mf
x <- mx
return (f x)
Which you can use all the time to turn a Monad into an Applicative.
Aside: Applicative is great.
In fact, whenever you find yourself writing
this thing = do
something <- some monadic thing
more <- some other thing
yetmore <- another thing too
return (combine something more yetmore)
you should rewrite it using applicative notation:
this thing = combine <$> some monadic thing
<*> some other thing
<*> another thing too
Maybe3 ais isomorphic toEither Bool a, perhaps that can guide you a bit. Otherwise, how about showing something you have tried, so as to see where you're experiencing problems? At least theFunctorinstance is really simple, as usual. - leftaroundabout<-). I feel it's an article worth advertising, so have taken this opportunity. - AndrewCLeft x >>= return = Left xand thereforeLeft x >>= f = Left xsince you can't pattern match on functions. Thus the only way it could be anything other than the usual instance forEither ais ifreturngave youLeft foofor somefoo.This though is impossible because of the other identity law:return x >>= \y -> Right y = Right x- Philip JFEitheronly requires a semi-group and not a monoid. This is becausepuredoes not have to use the identity. Thus you have other instances, such as the one generated byconst. I think you might have even more instances than the obvious ones using this semi-group construction. - Philip JF