1
votes

I'm completely stuck when solving a Monad assignment in Haskell course. There is a sample data type I want to define Monad-specific functions for:

data MyMonad a = MyMonad { func :: String -> a }

instance Functor MyMonad where
    fmap f (MyMonad x) = MyMonad (\a -> f (x a))   

instance Applicative MyMonad where
    pure x = MyMonad (\a -> x)
    (MyMonad f) <*> (MyMonad g) = MyMonad (\a -> (f a)(g a))

instance Monad MyMonad where
    return x = MyMonad (\a -> x)
    MyMonad x >>= f = f (\a -> x a) --my wrong definition 

Once Functor and Applicative instances declared, I'm trying to do the same for Monad, but...I'm not a little bit closer to understand how to fit a record syntax func into that f function. So far I see bind as a function to take an x of MyMonad before mapping it over f. It's just a cricial feature of any Monad - enable putting some values from one data type context to another one - as far as I realize that. To be honest, I'm aware of bind definitions in Monad instances for [a], Maybe and several other everpresent types. Yes, I see clearly what's a common purpose the Monad class serves for. However, I need to get any suggestion in this specific case just to enhance my understanding about the way to deal with something like records.

1

1 Answers

0
votes

The x in MyMonad x has as type String -> a, whereas f has as type a -> MyMonad b, we thus should return a MyMonad b (that wraps a function String -> b).

We thus should construct a function that maps a s :: String to a b. We can do that by first passing that s to the x function, and retrieve a value of type a. Next we can call f with a as that parameter, ands retrieve a MyMonad g. We can then apply that s to g.

We can thus implement the Monad instance as:

instance Monad MyMonad where
    return x = MyMonad (\a -> x)
    MyMonad x >>= f = MyMonad (\s -> let MyMonad g = f (x s) in g s)

since you defined a "getter" func :: MyMonad a -> a -> String, we can make use of that getter instead of using a let … in … expression to "unwrap" the value out of the MyMonad data constructor:

instance Monad MyMonad where
    return x = MyMonad (\a -> x)
    MyMonad x >>= f = MyMonad (\s -> func (f (x s)) s)