Reputation: 3682
Suppose I want to create a wrapping Monad that takes an IO Action and wraps it as follows. The sequence operator (>>) works just fine, but I'm having a hard time implementing return
and >>=
.
I tried return x = DelayedAction (return x)
but that doesn't result in the correct type.
newtype DelayedAction a = DelayedAction {action :: IO a}
instance Functor DelayedAction where
fmap = liftM
instance Applicative DelayedAction where
pure = return
(<*>) = ap
instance Monad DelayedAction where
return x = undefined
(DelayedAction firstIO) >>= f = undefined
(DelayedAction firstIO) >> (DelayedAction secondIO) =
DelayedAction
( do
firstIO
threadDelay 1000000
secondIO
)
Upvotes: 2
Views: 201
Reputation: 3682
@Aplet123 and @leftaroundabout clarified that this can't be a real monad since it can't follow Monad laws. Nonetheless, I was able to come up with a solution that made the compiler happy. Taught me a lot about monads, type-classes, types, do-notation, etc.
instance Monad DelayedAction where
return x = DelayedAction (return x)
da >>= f =
DelayedAction
( do
firstIOValue <- action da
threadDelay 1000000
(action . f) firstIOValue
)
De-sugared version of bind:
da >>= f =
DelayedAction
( action da >>= (\firstIOValue -> threadDelay 1000000 >> (action . f) firstIOValue)
Upvotes: 1