Что заставляет fmap работать здесь без явного объявления метода?

Одно из упражнений в Real World Haskell, гл. 24, просит реализовать оболочку строгости вокруг Control.Concurrent.MVar. Я делаю это, как предлагается в книге, используя оболочку newtype MVarS, чтобы гарантировать, что evaluate применяется ко всем аргументам, передаваемым таким функциям, как newMVar и putMVar.

Теперь одной из функций для переноса является mkWeakMVar, тип которой MVar a -> IO () -> IO (Weak (MVar a)). Предполагая, что мои функции построения MVarS реализуют строгость, я рассудил, что для mkWeakMVar будет достаточно поставить MVarS вместо его MVars. Поэтому я написал следующее:

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)

Похоже, это работает, даже несмотря на то, что GHCi предупреждает, что нет явного объявления метода fmap для Functor Weak. Но это оставляет меня заинтригованным. Что заставляет fmap работать в этом случае?


person Pablo    schedule 06.10.2014    source источник
comment
Это может работать только в том случае, если fmap для Weak никогда не вызывается.   -  person augustss    schedule 06.10.2014


Ответы (1)


В то время как приведенный выше код выполняет проверку типов, GHC аварийно завершает работу при попытке оценить значение, требующее вызова отсутствующей реализации fmap. Это будет выглядеть примерно так:

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

Поскольку это довольно катастрофическая ошибка во время выполнения, которую можно полностью избежать, она должна служить свидетельством важности -Wall.

person J. Abrahamson    schedule 06.10.2014