x
в MyMonad x
имеет тип String -> a
, в то время как f
имеет тип a -> MyMonad b
, поэтому мы должны вернуть MyMonad b
(который включает функцию String -> b)
.
Таким образом, мы должны сконструировать функцию, которая отображает s :: String
в b
. Мы можем сделать это, сначала передав s
функции x
, и получив значение типа a
. Затем мы мы можем вызвать f
с a
в качестве этого параметра и получить MyMonad g
. Затем мы можем применить это s
к g
.
Таким образом, мы можем реализовать экземпляр Monad
следующим образом:
instance Monad MyMonad where
return x = MyMonad (\a -> x)
MyMonad x >>= f = MyMonad (<b>\s -> let MyMonad g = f (x s) in g s</b>)
, так как вы определили "getter" func :: MyMonad a -> a -> String
, мы можем использовать этот getter вместо использования выражения let … in …
для "разворачивания" значения из конструктора данных MyMonad
:
instance Monad MyMonad where
return x = MyMonad (\a -> x)
MyMonad x >>= f = MyMonad (<b>\s -> func (f (x s)) s</b>)