使用MonadIO测试类型类:“没有实例也没有默认方法”错误

时间:2017-01-16 21:18:58

标签: haskell io-monad hspec

我有一个执行某些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

我尝试使用liftIO中的Control.Monad.IO.Class

-- C is the qualified import for Control.Monad.IO.Class
liftIO = C.liftIO

但这会导致NonTermination运行时异常:

uncaught exception: NonTermination (<<loop>>)

我有什么想法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

一种解决方案是支持IO中的真实WorkingDBM。例如:

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时显然会爆炸。