module Data.Maybe where

import Control.Monad
import Data.Function
import Data.Wrapper

data Maybe a = Nothing | Just a

maybe :: b -> (a -> b) -> Maybe a -> b
maybe y _ Nothing = y
maybe _ f (Just x) = f x

instance Functor Hask Maybe where
    _ $> Nothing = Nothing
    f $> Just x = Just $ f x

instance Pointed Hask Maybe where
    point = Just

instance Applicative Hask Maybe where
    Just f <$> Just x = Just $ f x
    _ <$> _ = Nothing

instance Monad Hask Maybe where
    join (Just (Just x)) = Just x
    join _ = Nothing

instance Monad Hask m => Functor (Kleisli Hask m) Maybe where
    ($>) = inWrapper $ maybe (point Nothing) . result (map Just)

instance Monad Hask m => Pointed (Kleisli Hask m) Maybe where
    point = Kleisli $ point . point

instance Monad Hask m => Applicative (Kleisli Hask m) Maybe where
    (<$>) = maybe (Kleisli . const . point $ Nothing) map

instance Monad Hask m => Monad (Kleisli Hask m) Maybe where
    extend = inWrapper . maybe . point $ Nothing
