[Haskell-beginners] How to create a monad in GHC 7.10 or newer

Ahmad Ismail ismail783 at gmail.com
Sun Nov 13 10:33:54 UTC 2022


In the book "Haskell programming from first principles" it is said that:

If you are using GHC 7.10 or newer, you’ll see an Applicative constraint in
> the definition of Monad, as it should be:



    class Applicative m => Monad m where
>         (>>=) :: m a -> (a -> m b) -> m b
>         (>>) :: m a -> m b -> m b
>         return :: a -> m a


I have created the following applicative functor.

data WhoCares a = ItDoesnt | Matter a | WhatThisIsCalled deriving (Eq, Show)

instance Functor WhoCares where
    fmap _ ItDoesnt = ItDoesnt
    fmap _ WhatThisIsCalled = WhatThisIsCalled
    fmap f (Matter a) = Matter (f a)

instance Applicative WhoCares where
    pure = Matter
    Matter f <*> Matter a = Matter (f a)

main = do

    -- fmap id == id
    let funcx = fmap id "Hi Julie"
    let funcy = id "Hi Julie"
    print(funcx)
    print(funcy)
    print(funcx == funcy)

    -- fmap (f . g) == fmap f . fmap g
    let funcx' = fmap ((+1) . (*2)) [1..5]
    let funcy' = fmap (+1) . fmap (*2) $ [1..5]
    print(funcx')
    print(funcy')
    print(funcx' == funcy')

    -- pure id <*> v = v
    print(pure id <*> (Matter 10))

    -- pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
    let appx = pure (.) <*> (Matter (+1)) <*> (Matter (*2)) <*> (Matter 10)
    let appy = (Matter (+1)) <*> ((Matter (*2)) <*> (Matter 10))
    print(appx)
    print(appy)
    print(appx == appy)

    -- pure f <*> pure x = pure (f x)
    let appx' = pure (+1) <*> pure 1 :: WhoCares Int
    let appy' = pure ((+1) 1) :: WhoCares Int
    print(appx')
    print(appy')
    print(appx' == appy')

    -- u <*> pure y = pure ($ y) <*> u
    let appx'' = Matter (+2) <*> pure 2
    let appy'' = pure ($ 2) <*> Matter (+ 2)
    print(appx'')
    print(appy'')
    print(appx'' == appy'')

Due to lack of examples, I am not understanding how to implement >>= and
>>. The code I came up with so far is:

instance Monad (WhoCares a) where
    (>>=) :: Matter a -> (a -> Matter b) -> Matter b
    (>>) :: Matter a -> Matter b -> Matter b
    return :: a -> Matter a
    return = pure

So, that I can do stuff like:

half x = if even x
            then Matter (x `div` 2)
            else ItDoesnt

incVal :: (Ord a, Num a) => a -> WhoCares a
incVal x
    | x + 1 <= 10 = return (x + 1)
    | otherwise = ItDoesnt

decVal :: (Ord a, Num a) => a -> WhoCares a
decVal x
    | x - 1 >= 0 = return (x - 1)
    | otherwise = ItDoesnt

main = do
    print (Matter 7 >>= incVal >>= incVal >>= incVal)
    print (Matter 7 >>= incVal >>= incVal >>= incVal >>= incVal)
    print (Matter 7 >>= incVal >>= incVal >>= incVal >>= incVal >>= decVal
>>= decVal)
    print (Matter 2 >>= decVal >>= decVal >>= decVal)
    print(Matter 20 >>= half >>= half)

With Output:

10
ItDoesnt
ItDoesnt
ItDoesnt
5

Please help.

*Thanks and Best Regards,Ahmad Ismail*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20221113/b0dec940/attachment.html>


More information about the Beginners mailing list