Why can I use `>> =` without explicit or implicit definition?

I defined type X as

 newtype X io = X { runX :: Int -> i -> IO o } 

I made an instance of Functor , Applicative and Monad with

 instance Functor (X i) where fmap fa = X $ \ io -> liftA f $ runX aio instance Applicative (X i) where pure x = X $ \ _ _ -> return x a <*> b = X $ \ io -> liftA2 (<*>) (runX aio) (runX bio) instance Monad (X i) where return = pure a >> b = X $ \ io -> runX aio >> runX bio 

As you might say, I, therefore, could not find a definition for >>= and therefore excluded it. I expected this to be a compilation error, but in fact all she did was a warning. Great, therefore, it does not check that all methods of the class are defined, but then I really can not use >>= . No, wrong again. To my great surprise, GHCi happily appreciates let x = pure 5 >>= pure . Control.Monad does not export the standard definition >>= , and I have definitely not defined it, since is this possible?

+6
source share
1 answer

Given your corrected definition, if I try to determine and then use x , I get the expected exception at runtime:

 λ> let x = pure 5 >>= pure :: X Int Int λ> runX x 5 5 *** Exception: foo.hs:12:10-20: No instance nor default method for class operation GHC.Base.>>= 

There are two possible reasons why you will not see this.

First of all, you just started let , but you never tried to evaluate the result. Since Haskell is lazy, let x = ... actually does nothing. x will only be evaluated when you are actually trying to use it (using, i.e. runX ), so when you click on the error.

Another possibility is that you used let without specifying a type:

 λ> let x = pure 5 >>= pure λ> x 5 

Here x is polymorphic in the monad m , which he uses. To print something useful for polymorphic terms like this, ghci defaults to m to IO , which works correctly and gives you 5 , but doesn't tell you anything useful about your custom monad.

+9
source

All Articles