Real World Haskell 中的一个练习,ch。 24,要求在Control.Concurrent.MVar
周围实现严格包装。我正如本书中所建议的那样,使用newtype
MVarS
包装器来确保将evaluate
应用于传递给newMVar
等函数的任何参数。 putMVar
。
现在,要包装的函数之一是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警告fmap
Functor Weak
没有明确的方法声明。但这让我很感兴趣。是什么让fmap
在这种情况下起作用?
答案 0 :(得分:10)
虽然上面的代码会进行类型检查,但在尝试评估需要调用缺少的fmap
实现的值时,GHC会崩溃。它看起来有点像:
*** Exception: /Users/tel/tmp/SO.hs:31:10-18:
No instance nor default method for class operation GHC.Base.fmap
由于这是一个相当灾难性并且完全可以避免的运行时错误,因此它应该证明-Wall
的重要性。