使用 MonadIO 测试类型类:"No instance nor default method" 错误
Testing a typeclass with MonadIO: "No instance nor default method" error
我有一个执行某些 IO 的类型类。我使用 MonadIO
:
对其进行了一些概括
class MonadIO m => MonadDB m where
getSomething :: String -> m Something
getSomething s = -- do some IO stuff with liftIO
在测试中我希望替换实现以便我可以测试使用 getSomething
的函数,所以我这样做:
newtype WorkingDBM a = WorkingDBM (Identity a)
deriving (Functor, Applicative, Monad)
instance MonadDB WorkingDBM where
getSomething s = return $ Something "blah"
如果没有实例声明,代码会警告:
• No explicit implementation for ‘liftIO’
• In the instance declaration for ‘MonadIO WorkingDBM’
所以我补充:
instance MonadIO WorkingDBM
当然可以编译。
运行 Hspec 中的测试导致此运行时错误:
uncaught exception: NoMethodError (test/BlahSpec.hs:45:10-33: No instance nor default method for class operation liftIO
我尝试使用 Control.Monad.IO.Class
中的 liftIO
:
-- C is the qualified import for Control.Monad.IO.Class
liftIO = C.liftIO
但这会导致 NonTermination
运行时异常:
uncaught exception: NonTermination (<<loop>>)
有什么办法可以解决这个问题吗?
一种解决方案是在 WorkingDBM
中支持真实的 IO
。例如:
newtype WorkingDBM a = WorkingDBM (IO a) -- N.B. IO not Identity
deriving (Functor, Applicative, Monad)
instance MonadIO WorkingDBM where
liftIO = WorkingDBM
MonadIO
的派生实例也可以正常工作;但是空实例不会,因为它等同于
instance MonadIO WorkingDBM where
liftIO = undefined
这显然会在您第一次尝试实际操作时爆炸 IO
。
我有一个执行某些 IO 的类型类。我使用 MonadIO
:
class MonadIO m => MonadDB m where
getSomething :: String -> m Something
getSomething s = -- do some IO stuff with liftIO
在测试中我希望替换实现以便我可以测试使用 getSomething
的函数,所以我这样做:
newtype WorkingDBM a = WorkingDBM (Identity a)
deriving (Functor, Applicative, Monad)
instance MonadDB WorkingDBM where
getSomething s = return $ Something "blah"
如果没有实例声明,代码会警告:
• No explicit implementation for ‘liftIO’
• In the instance declaration for ‘MonadIO WorkingDBM’
所以我补充:
instance MonadIO WorkingDBM
当然可以编译。
运行 Hspec 中的测试导致此运行时错误:
uncaught exception: NoMethodError (test/BlahSpec.hs:45:10-33: No instance nor default method for class operation liftIO
我尝试使用 Control.Monad.IO.Class
中的 liftIO
:
-- C is the qualified import for Control.Monad.IO.Class
liftIO = C.liftIO
但这会导致 NonTermination
运行时异常:
uncaught exception: NonTermination (<<loop>>)
有什么办法可以解决这个问题吗?
一种解决方案是在 WorkingDBM
中支持真实的 IO
。例如:
newtype WorkingDBM a = WorkingDBM (IO a) -- N.B. IO not Identity
deriving (Functor, Applicative, Monad)
instance MonadIO WorkingDBM where
liftIO = WorkingDBM
MonadIO
的派生实例也可以正常工作;但是空实例不会,因为它等同于
instance MonadIO WorkingDBM where
liftIO = undefined
这显然会在您第一次尝试实际操作时爆炸 IO
。