[英]How to fix type errors, including “Can't quantify over Traversable”, when generifying this SOP function?
我只想说我什至不确定这是否可能; 这是迄今为止我在 Haskell 中尝试过的最通用的事情。 我正在尝试制作https://stackoverflow.com/a/58890226/3096687中的applyFunc
的更通用版本:
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 _)
类似的错误也发生在其他地方。
我不能确定这会解决所有问题,因为很难重现你的问题:它需要很多我没有时间设置的包和导入(提示:将来,尽量减少您的问题在发布之前尽量减少可重复的示例)。 但是我还是要发布这个,因为我至少可以看到一个问题,并且它似乎与错误消息有关。
问题是第一行的t
和第三行的t
不一样,而且它们都和第五行的t
不同。 依此类推,对于所有涉及t
的类型签名。
默认情况下,在 Haskell2010 中,每个类型变量的 scope 只是引入它的类型签名。 如果您在另一个类型签名中使用相同的字母,它将表示完全独立的类型,尽管看起来与人眼相同。
要指定您实际上意味着t
在任何地方都相同,您必须在顶部类型签名中使用forall
:
applyRecFun :: forall t. (Traversable t, _) => Record (SummaryFun t) _ -> t r -> r
由ScopedTypeVariables
扩展启用, forall
关键字为类型变量t
创建显式 scope 。 范围有不同的风格,但是当在函数的类型签名中打开时,范围的范围是 function 的整个主体。
我不确定这是否会为您解决所有问题,但至少您现在应该遇到不同的错误。
基于 Fyodor 的回答,我有一个正在编译(但尚未测试)的代码。 我不得不更改类型签名中的一些假设,例如返回包含在Maybe
中的结果,并假设Traversable
也是 forms 一个Semigroup
。 一旦我有机会按照 Fyodor 的建议正确测试和构建一个独立的示例,我将修改问题的措辞和这个答案:
newtype SummaryFun t a = SummaryFun (t a -> a)
applyRecFun :: forall r t. (Traversable t, Semigroup (t r), _) =>
Record (SummaryFun t) _ -> t r -> Maybe r
applyRecFun func recs =
let recsNP :: t (NP I _) -- a traversable of n-ary products. I is an identity functor
recsNP = toNP . toRecord <$> recs
listrecsNP :: t (NP t _) -- turn every component into a singleton traversable
listrecsNP = liftA_NP (\(I x) -> pure x) <$> recsNP
listrecNPmay :: Maybe (NP t _) -- a single n-ary product where each component is a traversable
listrecNPmay = listrecsNP & (headMay &&& tailMay) & sequenceT
<&> (\(h, t) -> foldr mappend h t)
funcNP :: NP (SummaryFun t) _ -- turn the function record into a n-ary prod
funcNP = toNP func
toRec_NP_I :: NP t _ -> NP I _ -- apply the functions to each list component
toRec_NP_I = liftA2_NP (\(SummaryFun f) vs -> I (f vs)) funcNP
in do
listrecNP <- listrecNPmay
let resultRec_NP_I = toRec_NP_I listrecNP
pure $ fromRecord . fromNP $ resultRec_NP_I -- go back to the nominal record Rec
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.