测试套件中的“(MonadLevelDB IO)没有实例”编译错误

时间:2019-04-25 07:04:38

标签: haskell leveldb

我正在尝试在Haskell应用程序中使用higher-leveldb,但在我的测试套件中遇到了我不理解的编译错误(或者至少我不知道如何正确修复它)

对于上下文,我有以下帮手可以从数据库中获取和解码用户:

getUser :: (MonadLevelDB m) => Text -> m (Maybe User)
getUser uuid = do
  let key = toStrict . encode $ uuid
  result <- LevelDB.get key -- m (Maybe Value)
  case result of
      Just value -> return ( decodeStrict' value :: Maybe User) -- Ideal type
      Nothing    -> return Nothing

以及以下测试套件:


type EuphrateMonad m = (MonadLevelDB m, MonadUnliftIO m, MonadIO m)

main :: IO ()
main = runCreateLevelDB "/tmp/mydb" "test" levelDBMain

levelDBMain :: (EuphrateMonad m) => m ()
levelDBMain = do
    setup
    test <- liftIO $ testSpec "euphrate" spec
    liftIO $ Test.Tasty.defaultMain test


spec :: Spec
spec = parallel $ do
    it "Fetch an already-existing user" $ do
        user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
        user `shouldBe` ( Just $ User "toto" "664798e1-7fac-4e0b-9fc6-757f4fb0409c" True "toto92" "" )

    it "Delete a user" $ do
      deleteUser "2e940724-936e-4700-826b-367faabac141"
      user <- getUser "2e940724-936e-4700-826b-367faabac141"
      user `shouldBe` Nothing

users :: [User]
users = [ User "toto" "664798e1-7fac-4e0b-9fc6-757f4fb0409c" True "toto92" ""
        , User "Jérôme" "2e940724-936e-4700-826b-367faabac141" False "jéjédu32" "nah."
        ]

setup :: (EuphrateMonad m) => m ()
setup =
  for_ users createUser

现在,我得到的错误是:

euphrate/test/Main.hs:29:17: error:
    • No instance for (MonadLevelDB IO) arising from a use of ‘getUser’
    • In a stmt of a 'do' block:
        user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
      In the second argument of ‘($)’, namely
        ‘do user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
            user
              `shouldBe`
                (Just
                   $ User
                       "toto" "664798e1-7fac-4e0b-9fc6-757f4fb0409c" True "toto92" "")’
      In a stmt of a 'do' block:
        _ <- it "Fetch an already-existing user"
               $ do user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
                    user
                      `shouldBe`
                        (Just
                           $ User
                               "toto" "664798e1-7fac-4e0b-9fc6-757f4fb0409c" True "toto92" "")
   |
29 |         user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我首先要寻找一种方法来更好地了解这种情况。通过阅读器和编写器,我对变压器有一些基本的了解,但是我对所了解的并没有太大的帮助。

感谢您的阅读:)

1 个答案:

答案 0 :(得分:1)

我对高级数据库不熟悉,但是从代码的外观来看,我认为问题可能是当您编写如下代码行时:

spec :: Spec
spec = parallel $ do
    it "Fetch an already-existing user" $ do
        user <- getUser "664798e1-7fac-4e0b-9fc6-757f4fb0409c"
        user `shouldBe` ( Just $ User "toto" "664798e1-7fac-4e0b-9fc6-757f4fb0409c" True "toto92" "" )

您不在所需的单子语境中。使用it只能生活在hspec上下文中,该上下文不了解所有与DB相关的事情。看一下it的(相当抽象的)签名:

it :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a)

我们远远没有限制您的EuphrateMonad堆栈。因此,您需要在两者之间添加一些内容,以输入所需的上下文(获得与levelDB的连接,管理事务等)。

在这种情况下,我发现直接查看库代码并查看是否有任何测试套件以及作者如何创建其上下文会有所帮助。 there are tests in this library,您真幸运。查看withDBTwithDBRT的定义和使用,这应该为您指明正确的方向。