[英]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.