我正在尝试在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"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我首先要寻找一种方法来更好地了解这种情况。通过阅读器和编写器,我对变压器有一些基本的了解,但是我对所了解的并没有太大的帮助。
感谢您的阅读:)
答案 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,您真幸运。查看withDBT
和withDBRT
的定义和使用,这应该为您指明正确的方向。