Я узнал, как проектировать тестируемые компоненты, и у меня возникла проблема. Мой пример кода:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Test where
import Control.Monad.Reader
import Data.Functor.Identity
class Monad m => TestMonad m where
test :: Int -> m Int
data TestData m = TestData {
_test :: Int -> m Int
}
instance (Monad m, MonadReader (TestData m) m) => TestMonad m where
test n = ask >>= \(TestData f) -> f n
env :: TestData Identity
env = TestData {
_test = return
}
Если я хочу запустить этот пример
runReader (test 5) env
, я получаю эту ошибку:
*Test Control.Monad.Reader> runReader (test 5) env
<interactive>:5:12: error:
• Couldn't match type ‘Identity’
with ‘ReaderT (TestData Identity) Identity’
arising from a functional dependency between:
constraint ‘MonadReader
(TestData (ReaderT (TestData Identity) Identity))
(ReaderT (TestData Identity) Identity)’
arising from a use of ‘test’
instance ‘MonadReader r (ReaderT r m)’ at <no location info>
• In the first argument of ‘runReader’, namely ‘(test 5)’
In the expression: runReader (test 5) env
In an equation for ‘it’: it = runReader (test 5) env
*Test Control.Monad.Reader>
Что я делаю неправильно и как починю?
Вопрос снят. Нашел свою ошибку. У меня есть типы env :: TestData Identity
и test 5 :: ReaderT (TestData Identity) Identity
. Но мой экземпляр охватывает только случай test 5 :: ReaderT (TestData m) Identity
, где m ~ ReaderT (TestData m) Identity
.
Правильный экземпляр:
instance TestMonad (Reader (TestData Identity)) where
test n = do
(TestData f) <- ask
return $ runIdentity $ f n