ch。Real World Haskell中的练习之一。 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
在这种情况下起作用? 最佳答案
虽然上面的代码将进行类型检查,但是在尝试评估需要调用缺少的fmap
实现的值时,GHC将崩溃。看起来有点像:
*** Exception: /Users/tel/tmp/SO.hs:31:10-18:
No instance nor default method for class operation GHC.Base.fmap
由于这是一个灾难性且完全可以避免的运行时错误,因此应证明
-Wall
的重要性。