2017-01-16 13 views
0

일부 IO를 수행하는 typeclass가 있습니다. 내가 getSomething을 사용하는 기능을 테스트 할 수 있도록 구현을 대체하고자하는 테스트에서MonadIO를 사용하여 typeclass 테스트 : "인스턴스 또는 기본 방법 없음"오류

class MonadIO m => MonadDB m where 
    getSomething :: String -> m Something 
    getSomething s = -- do some IO stuff with liftIO 

, 그래서이 할 : 나는 그것을 MonadIO 사용하여 조금 일반화 한없이

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에서 테스트를 실행

이 런타임 오류가 발생합니다

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

그러나 이것은 NonTermination 런타임 예외가 발생합니다 :

uncaught exception: NoMethodError (test/BlahSpec.hs:45:10-33: No instance nor default method for class operation liftIO 

내가 사용 시도를 liftIOControl.Monad.IO.Class에서

uncaught exception: NonTermination (<<loop>>) 

아이디어를 어떻게 해결할 수 있습니까? 그의 제발?

+0

테스트에서'IO'를하지 않거나'WorkingDBM'에서 실제'IO'를 지원하지 마십시오. –

+0

테스트 중이던 함수에서'liftIO'라고 밝혀 졌기 때문에 IO를 수행 할 수 없습니다. 진짜를지지한다는 것은 무엇을 의미합니까? 나는 Monadio만으로 충분하다고 생각했다. –

+1

나는 내가 의미하는 바에 대한 좀 더 자세한 내용을 담은 답을 썼다. 하지만 테스트에서'MonadDB' 인스턴스 안에서'IO'를해야한다는 주장에 도전합니다. –

답변

1

IOWorkingDBM에 지원하는 것이 하나의 솔루션입니다. 예를 들면 :

newtype WorkingDBM a = WorkingDBM (IO a) -- N.B. IO not Identity 
    deriving (Functor, Applicative, Monad) 

instance MonadIO WorkingDBM where 
    liftIO = WorkingDBM 

MonadIO도 잘 작동에 대한 파생 예; 그것은 분명히 실제로 IO을 할 당신이 시도 처음으로 날려 버리겠다

instance MonadIO WorkingDBM where 
    liftIO = undefined 

에 해당로하지만 빈 인스턴스가되지 않습니다.

+0

감사합니다. 어떻게하면 'WorkingDBM'을 강제로 사용할 수 있습니까? 나는 현재 테스트에서'unWorkingDBM (WorkingDBM (Identity x)) = x'을 사용하여 컴파일러가'MonadDB'의 "teset 인스턴스"를 사용하도록합니다. 'IO a'가 사용되었을 때 (IO가 데이터 생성자가 없기 때문에) 컴파일러를 밀어 넣을 수 없다는 것을 의미합니다. –

+0

@atc 여전히' runWorkingDBM (WorkingDBM x) = x'라면,'runWorkingDBM :: WorkingDBM a -> a'보다는'runWorkingDBM :: WorkingDBM a -> IO a '타입을 주면됩니다. –

+0

도움을 주셔서 감사합니다. ! :) –