{-# OPTIONS_GHC -fno-warn-noncanonical-monad-instances #-}

module Class240423 where

-- Let's reimplement the Maybe-monad from scratch

-- Disable the native implementation
import Prelude hiding (Maybe, Just, Nothing)

-- Define it as an algebraic data type
data Maybe a = Just a | Nothing

-- This is redundant for the example, but Haskell disallows 
-- instances of Monad without being an instance of Functor
instance Functor Maybe where
    fmap f p = p >>= return . f

-- Same here
instance Applicative Maybe where
    pure = return
    f <*> p = f >>= \g-> (p >>= return . g)

-- Finally:
instance Monad Maybe where
    return = Just 
    -- "p >>= q" is the same as "do <- p; q x", but Haskell.
    -- requires the >>=-syntax for implementing instances.
    p >>= q = case p of Just x -> q x; Nothing -> Nothing
