首页 > 解决方案 > 生成此 SOP 函数时,如何修复类型错误,包括“无法对 Traversable 进行量化”?

问题描述

我只想说我什至不确定这是否可能;这是迄今为止我在 Haskell 中尝试过的最通用的事情。我正在尝试制作https://stackoverflow.com/a/58890226/3096687applyFunc中的更通用版本:

newtype SummaryFun t a = SummaryFun (t a -> a)

applyRecFun :: (Traversable t, _) => Record (SummaryFun t) _ -> t r -> r
applyRecFun func recs =
  let recs_NP :: t (NP I _) -- a list of n-ary products. I is an identity functor
      recs_NP = toNP . toRecord <$> recs
      listrecs_NP :: t (NP t _) -- turn every component into a singleton list
      listrecs_NP = liftA_NP (\(I x) -> pure x) <$> recs_NP
      listrec_NP :: NP t _ -- a single n-ary product where each component is a list
      listrec_NP = mconcat listrecs_NP
      func_NP :: NP (SummaryFun t) _ -- turn the function record into a n-ary prod
      func_NP = toNP func
      resultRec_NP_I :: NP I _ -- apply the functions to each list component
      resultRec_NP_I = liftA2_NP (\(SummaryFun f) vs -> I (f vs)) func_NP listrec_NP
   in fromRecord . fromNP $ resultRec_NP_I -- go back to the nominal record Rec

遇到的第一个问题是:

• Can't quantify over ‘t’                  
    bound by the partial type signature: recs_NP :: t (NP I _)

类似的错误也发生在其他地方。

标签: haskellgenerics

解决方案


我不能确定这会解决所有问题,因为很难重现你的问题:它需要很多我没有时间设置的包和导入(提示:将来,尽量减少您的问题在发布之前尽量减少可重复的示例)。但是我还是要发布这个,因为我至少可以看到一个问题,并且它似乎与错误消息有关。


问题是t第一行和第三行不一样t,它们都t与第五行不同。依此类推,对于所有涉及t.

默认情况下,在 Haskell2010 中,每个类型变量的作用域只是引入它的类型签名。如果您在另一个类型签名中使用相同的字母,它将表示完全独立的类型,尽管看起来与人眼相同。

要指定您实际上意味着t在任何地方都相同,您必须forall在顶部类型签名中使用:

applyRecFun :: forall t. (Traversable t, _) => Record (SummaryFun t) _ -> t r -> r

ScopedTypeVariables由扩展启用,关键字为类型变量forall创建显式范围t。范围有不同的风格,但是当在函数的类型签名中打开时,范围的范围是该函数的整个主体。

我不确定这是否会为您解决所有问题,但至少您现在应该遇到不同的错误。


推荐阅读