Haskell проектирование тестируемых компонентов - PullRequest
2 голосов
/ 07 мая 2020

Я узнал, как проектировать тестируемые компоненты, и у меня возникла проблема. Мой пример кода:

{-# 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...