Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What makes fmap work here without an explicit method declaration?

One of the exercises in Real World Haskell, ch. 24, asks to implement a strictness wrapper around Control.Concurrent.MVar. I am doing this, as suggested in the book, by using a newtype MVarS wrapper to ensure that evaluate is applied to whatever arguments get passed to functions such as newMVar and putMVar.

Now, one of the functions to wrap is mkWeakMVar, whose type is MVar a -> IO () -> IO (Weak (MVar a)). Assuming that my MVarS builder functions implement strictness, I reasoned that for mkWeakMVar it would suffice to put MVarS in place of its MVars. So I wrote the following:

import           Control.Concurrent.MVar
import           System.Mem.Weak

instance Functor Weak

newtype MVarS a = MVarS (MVar a)

mkWeakMVarS :: MVarS a -> IO () -> IO (Weak (MVarS a))
mkWeakMVarS (MVarS mv) x = (fmap . fmap) MVarS (mkWeakMVar mv x)

This appears to work, even though GHCi warns that there is no explicit method declaration of fmap for Functor Weak. But it leaves me intrigued. What makes fmap work in this case?

like image 537
Pablo Avatar asked Sep 03 '26 04:09

Pablo


1 Answers

While the above code will typecheck, GHC will crash when attempting to evaluate a value which requires calling upon the missing fmap implementation. It'll look a bit like:

*** Exception: /Users/tel/tmp/SO.hs:31:10-18: 
    No instance nor default method for class operation GHC.Base.fmap

Since this is a rather catastrophic and entirely avoidable runtime error it ought to serve as a testament to the importance of -Wall.

like image 177
J. Abrahamson Avatar answered Sep 05 '26 11:09

J. Abrahamson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!