У меня есть класс, который выполняет некоторые операции ввода-вывода. Я обобщил его немного с помощью MonadIO
:Тестирование класса с помощью 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>>)
Любые идеи, как я могу решить t его, пожалуйста?
Не выполняйте 'IO' в своем тесте или поддерживайте реальный' IO' в 'WorkDBM'. –
Оказывается, это была 'liftIO' в функции, которую я тестировал, поэтому я не могу _not_ сделать IO. Что значит поддержка реальной? Я думал, что для этого достаточно «Монадио». –
Я написал ответ с некоторыми подробностями о том, что я имею в виду. Но я оспорю ваше утверждение о том, что вы должны выполнить 'IO' внутри экземпляра« MonadDB »в своем тесте. –