I'm a beginner and I'm trying to use Hoed to trace Haskell evaluations, because maybe it will further help my learning process.
I saw in their examples code like this
isEven :: Int -> Bool
isEven = observe "isEven" isEven'
isEven' n = mod2 n == 0
I was thinking how could I observe
in order to trace an instance defined function like >>=
for example.
I wrote something like
bind' = observe "bind'" (>>=)
and of course I've got an error
* Ambiguous type variable 'm0' arising from a use of '>>='
prevents the constraint '(Monad m0)' from being solved.
Relevant bindings include
bind' :: m0 a0 -> (a0 -> m0 b0) -> m0 b0 (bound at my.hs:46:1)
Probable fix: use a type annotation to specify what 'm0' should be.
These potential instances exist:
...
Should I / How could I use a type annotation in order to specify which Monad
instance's (e.g. Reader, State etc.) >>=
function
It looks like you have found the infamous MonomorphismRestriction
. More info. The links do a great job of explaining what the MonomorphismRestriction is and how it works.
You're not wrong to expect that writing bind'
with no signature should "just work". However, sometimes the compiler needs a bit of help. In short, due to the MonomorphismRestriction, GHC tries to take the nominally polymorphic signature of bind' :: Monad m => m a -> (a -> m b) -> m b
, and make it less polymorphic by instantiating some of the type variables.
In your case, it looks like the compiler wants to make bind'
only work for one specific Monad m
. Without your real code, I can't say for sure, but consider this example:
import Debug.Trace
main :: IO ()
main = (>>=) (return "hello") print
bind' = trace "bind" (>>=)
The compiler produces an error similar to yours: Ambiguous type variable m0
However, if you use bind'
:
import Debug.Trace
main :: IO ()
main = bind' (return "hello") print
bind' = trace "bind" (>>=)
no error! That's because GHC is inferring that m
should be IO
since bind'
is used in the IO
monad.
Alternatively, you can tell GHC to turn off the MonomorphismRestriction:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace
main :: IO ()
main = (>>=) (return "hello") print
bind' = trace "bind" (>>=)
and it compiles just fine!