ch。Real World Haskell中的练习之一。 24,要求围绕Control.Concurrent.MVar实现严格包装。正如书中所建议的,我这样做是通过使用newtype MVarS包装器来确保将evaluate应用于传递给函数的任何参数,例如newMVarputMVar

现在,要包装的函数之一是mkWeakMVar,其类型是MVar a -> IO () -> IO (Weak (MVar a))。假设我的MVarS构建器函数实现了严格性,我认为对于mkWeakMVar来说,只需用MVarS代替其MVar即可。所以我写了以下内容:

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警告没有针对fmapFunctor Weak的显式方法声明,这似乎仍然有效。但这让我很感兴趣。是什么让fmap在这种情况下起作用?

最佳答案

虽然上面的代码将进行类型检查,但是在尝试评估需要调用缺少的fmap实现的值时,GHC将崩溃。看起来有点像:

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

由于这是一个灾难性且完全可以避免的运行时错误,因此应证明-Wall的重要性。

08-28 17:19