我正在尝试在我的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"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我首先要找到更好地理解这种情况的方法。我通过读者和作家对变形金刚有一些基本的了解,但我对此所知并不感到很有帮助。
谢谢阅读 :)
我不熟悉高级数据库,但从代码的外观来看,我认为问题可能是当你编写这样的行时:
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" "" )
你不是在你需要的monadic环境中。使用it
你只能生活在hspec上下文中,它不知道所有与DB相关的东西。看看it
的(相当抽象的)签名:
it :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a)
我们远离你的EuphrateMonad
堆栈的约束。因此,您需要在两者之间添加一些内容,以输入所需的上下文(获取与levelDB的连接,管理事务等)。
在这种情况下,我发现直接查看库代码并查看是否有任何测试套件以及作者如何创建其上下文是有帮助的。你很幸运,there are tests in this library。看看withDBT
和withDBRT
的定义和用法,这应该指向正确的方向。