简体   繁体   中英

How to define `bind` for a type with record syntax in Haskell?

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.

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 ()

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 ()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM