Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have defined a type X as

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

I have made an instance of Functor, Applicative and Monad with

instance Functor (X i) where
  fmap f a = X $ \ i o -> liftA f $ runX a i o

instance Applicative (X i) where
  pure x  = X $ \ _ _ -> return x
  a <*> b = X $ \ i o -> liftA2 (<*>) (runX a i o) (runX b i o)

instance Monad (X i) where
  return = pure
  a >> b = X $ \ i o -> runX a i o >> runX b i o

As you could probably tell, I have been, thusfar, unable to come up with a definition for >>=, and so have excluded it. I expected this to error on compile, but in fact, all it did was raise a warning. Fine, so it doesn't check that all the methods of a class are defined, but then surely I can't actually use >>=. Nope, wrong once again. To my great astonishment, GHCi happily evaluates let x = pure 5 >>= pure. Control.Monad does not export a default definition of >>=, and I certainly haven't defined one, so how is this possible?

like image 432
Kwarrtz Avatar asked Aug 29 '15 00:08

Kwarrtz


People also ask

Why is there a need to distinguish between explicit and implicit claims whenever we critically read a text?

Critical reading also means that you are able to distinguish the information that is clear stated. EXPLICIT in the text from ideas that are suggested. IMPLICIT this is will help you make inferences about what your read.


1 Answers

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

λ> 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 would not see that.

The first is that you just ran the let but never tried evaluating the result. Since Haskell is lazy, let x = ... doesn't actually do anything. x will only get evaluated when you actually try to use it (with, ie, runX), so that's when you would hit the error.

The other possibility is that you used a let without specifying the type:

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

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

like image 131
Tikhon Jelvis Avatar answered Sep 21 '22 00:09

Tikhon Jelvis