尽管函数上下文中有条目,但 Ghc 无法推断 mtl 实例的使用

Ghc can't infer the use of mtl instances despite entries in the function context

我有一个 API 可以帮助从大量记录链中提取值。这是函数定义之一。其他示例,使用日志类型类功能。

-- |
-- Unifying filter for FieldValues
-- The "failed" search returns a null set.
--
filterValues, filterQualReqValues
  :: (MonadLogger m, MonadThrow m)
  => FieldValues -> FieldValues
  -> m FieldValues
filterValues (TxtSet s) (TxtSet vs)   = pure . TxtSet  $ Set.intersection s vs
filterValues (IntSet s) (IntSet vs)   = pure . IntSet  $ Set.intersection s vs
filterValues (SpanSet s) (SpanSet vs) = pure . SpanSet $ Set.intersection s vs
filterValues s _                      = throw $ TypeException (Just . pack $ show s)
filterQualReqValues = filterValues

我尝试使用 API...

fetchQualities :: (MonadLogger m, MonadThrow m)
               => [GqlInput.QualityReqInput] -> Model.Qualities
               -> m (Maybe Model.ReqQualities)
fetchQualities requests etl = 
  let
      -- wrap, process using shared logic, unwrap
      (subSetReqs, fullSetReqs) = mapTuple (catMaybes . (fmap unWrapQual))
                                $ ppSubsetting (Qual <$> requests)

      fullSetReqs' :: (MonadLogger m, MonadThrow m)
                   => m [(Model.QualName, Maybe Model.QualValues)]
      fullSetReqs' = catMaybes <$> traverse (`fetchFullSet` etl) fullSetReqs

      subSetReqs' :: (MonadLogger m, MonadThrow m)
                  => m [(Model.QualName, Maybe Model.QualValues)]
      subSetReqs' = catMaybes <$> traverse (`fetchSubset` etl) subSetReqs

      result :: (MonadLogger m, MonadThrow m)
             => m Model.ReqQualities
      result = (<>) <$> (Model.fromListReqQualities <$> subSetReqs') -- <<< subSetReqs' error
               <*> Model.fromListReqQualities <$> fullSetReqs'
   in
      do
        result' :: Model.ReqQualities <- result
        if Model.null result' then pure Nothing
                              else pure $ Just result'

   where

    fetchSubset :: (MonadLogger m, MonadThrow m)
                => GqlInput.QualityReqInput
                -> Model.Qualities
                -> m (Maybe (Model.QualName, Maybe Model.QualValues))

    fetchSubset req etl' = do
      -- process key
      reqWithValues <- getEtlFragment req etl' :: (MonadLogger m, MonadThrow m) => m (Maybe (Model.QualName, Model.QualValues))
      case reqWithValues of
        Nothing -> pure Nothing
        Just (key, etlValues) -> do
          -- process values
          let valuesReq  = GqlInput.qualityValues req  -- :: Maybe GqlInput.QualValuesInput
          case valuesReq of
            Nothing         -> pure $ Just (key, Nothing)
            Just valuesReq' -> do
              let valuesReq'' = fromInputReqQualValues valuesReq'
              values <- filterQualReqValues valuesReq'' etlValues
              if Model.null values then pure Nothing
                                   else pure $ Just (key, Just values)


    fetchFullSet :: (MonadLogger m, MonadThrow m)
                 => GqlInput.QualityReqInput
                 -> Model.Qualities
                 -> m (Maybe (Model.QualName, Maybe Model.QualValues))
    fetchFullSet req etl' = do
      let reqName = getQualName req
      case reqName of
         Nothing   -> pure Nothing        -- no key in the request
         Just name -> do
            key <- lookupQualityKey (Model.mkQualKey name) etl'
            pure ((,Nothing) <$> key)       -- key determines return

我收到一个错误

• Could not deduce (MonadLogger
                          ((->) [(Model.ETL.Key.QualKey, Maybe Model.QualValues)]))
        arising from a use of ‘subSetReqs'’
      from the context: (MonadLogger m, MonadThrow m)
        bound by the type signature for:
                   fetchQualities :: forall (m :: * -> *).
                                     (MonadLogger m, MonadThrow m) =>
                                     [GqlInput.QualityReqInput]
                                     -> Model.Qualities -> m (Maybe Model.ReqQualities)
        at src/Api/GQL/Input/SubRequest.hs:(143,1)-(145,46)

尽管类型注释数量惊人,并确保其中 none 实际上阻止了 ghc 推断某些东西,但我无法找到解决此错误的方法。我可以推断出我是 creating/inferring m?

的一个单独实例

如有任何建议或帮助,我们将不胜感激。

- E

如果您仔细查看错误消息:

Could not deduce (MonadLogger
                  ((->) [(Model.ETL.Key.QualKey, Maybe Model.QualValues)]))
arising from a use of subSetReqs'

您看到 GHC 已经决定它需要一个 MonadLogger 实例用于部分功能应用程序。具体来说,它试图为 (->) some_type 使用隐式 reader monad 实例(这很奇怪)并期望该类型支持日志记录(这很疯狂)。

这意味着您的程序中存在类型错误。

在我看来,您至少希望在错误 之后的 行中添加一些额外的括号:

<*> (Model.fromListReqQualities <$> fullSetReqs')
    ^                                           ^
    `---------------- add these ----------------'