没有因使用“lookupBlob”而产生的 (Git.Libgit2.HasLgRepo IO) 实例

问题描述

我正在尝试使用 gitlib 从 git 存储库中获取 HEAD 提交中所有文件的列表。这是我的代码

expect(received).toBeCalled()

Matcher error: received value must be a mock or spy function

Received has value: undefined

我得到的错误是:

{-# LANGUAGE OverloadedStrings #-}

module GitOperations where

import Git
import Git.Libgit2 (lgFactory,LgRepo(..) )
import qualified Data.Text as T
import Control.Monad.Trans.Reader
import Control.Monad.Trans
import Data.ByteString.Char8 as BS

repositoryOptions :: RepositoryOptions
repositoryOptions = RepositoryOptions { repoPath = ".git",repoWorkingDir = Just ".",repoIsBare = False,repoautocreate = True}
  
main :: IO ()
main = do
  repo <- openRepository lgFactory repositoryOptions
  runReaderT listHEADFiles repo

listHEADFiles:: ReaderT LgRepo IO ()
listHEADFiles = do 
  ref <- resolveReference $ T.pack "HEAD"
  case ref of
    nothing -> fail $ "Could not resolve reference named 'HEAD'"
    Just reference -> do
      obj <- lookupObject reference
      case obj of
        CommitObj commit -> do 
          objects <- listAllObjects (Just $ commitOid commit) (commitOid commit)
          lift $ mapM_ (\o -> case o of BlobObjOid boOid -> do blob <- lookupBlob boOid; bc <- blobContents blob; case bc of BlobString bs -> BS.putStrLn bs) objects
        _ -> fail $ "'HEAD' is not a commit object"

我不明白如何解决错误消息以及如何调整我的代码以使 typechecker 满意。任何提示表示赞赏。

请注意,git 存储库应至少包含一个提交才能使脚本正常工作。

UPD:根据@chi 的建议,我已将 Main.hs:33:96: error: • Couldn't match kind ‘* -> *’ with ‘*’ When matching types IO :: * -> * BlobContents :: (* -> *) -> * Expected type: IO (BlobContents m0) Actual type: BlobContents IO • In a stmt of a 'do' block: bc <- blobContents blob In the expression: do blob <- lookupBlob boOid bc <- blobContents blob case bc of { BlobString bs -> BS.putStrLn bs } In a case alternative: BlobObjOid boOid -> do blob <- lookupBlob boOid bc <- blobContents blob case bc of { BlobString bs -> BS.putStrLn bs } | 33 | lift $ mapM_ (\o -> case o of BlobObjOid boOid -> do blob <- lookupBlob boOid; bc <- blobContents blob; case bc of BlobString bs -> BS.putStrLn bs) objects | ^^^^^^^^^^^^^^^^^ Failed,no modules loaded. 调用更改为非 monadic,但现在相关行看起来像 blobContents blob,出现另一个错误,我不知道如何修复它:

lift $ mapM_ (\o -> case o of BlobObjOid boOid -> do blob <- lookupBlob boOid; let bc = blobContents blob in case bc of BlobString bs -> BS.putStrLn bs) objects

我对 Main.hs:33:72: error: • No instance for (Git.Libgit2.HasLgRepo IO) arising from a use of ‘lookupBlob’ • In a stmt of a 'do' block: blob <- lookupBlob boOid In the expression: do blob <- lookupBlob boOid let bc = ... in case bc of { BlobString bs -> BS.putStrLn bs } In a case alternative: BlobObjOid boOid -> do blob <- lookupBlob boOid let ... in case bc of { BlobString bs -> ... } | 33 | lift $ mapM_ (\o -> case o of BlobObjOid boOid -> do blob <- lookupBlob boOid; let bc = blobContents blob in case bc of BlobString bs -> BS.putStrLn bs) objects | ^^^^^^^^^^^^^^^^ Failed,no modules loaded. 还很陌生,现在我尝试在 Haskell 中使用 git 使简单的事情变得简单,这让我感到不知所措。有没有人知道如何使这段代码成功编译?

解决方法

如果我找到 the correct documentation pageblobContents 看起来像一个非 monadic 函数,所以你不能使用 bc <- blobContents blob。改用 let bc = blobContents blob

这与错误消息一致,错误消息指出实际类型未包装在 IO 下。

  Expected type: IO (BlobContents m0)
    Actual type: BlobContents IO

此外,您过早使用 lift

lift $ mapM_ (\o -> case o of 
   BlobObjOid boOid -> do
      blob <- lookupBlob boOid
      let bc = blobContents blob
      case bc of BlobString bs -> BS.putStrLn bs
   ) objects

lift 中,您只能使用 IO 操作,不能使用需要 ReaderT LgRepo IO 的操作。要解决此问题,只需将 lift 向内移动:

mapM_ (\o -> case o of 
   BlobObjOid boOid -> do
      blob <- lookupBlob boOid
      let bc = blobContents blob
      case bc of BlobString bs -> lift $ BS.putStrLn bs
   ) objects