我的数据类型,总会有至少两个参数,最后两个参数分别总是“Q”和“M”,:类型解构
{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds, ConstraintKinds, FlexibleInstances #-}
data D1 q m = D1 q
data D2 t q m = D2 q
class Foo a where -- a has kind * -> *
f :: a x -> a x
class (Foo b) => Bar b where -- b has kind * -> *
-- the purpose of g is to change ONE type parameter, while fixing the rest
-- the intent of the equality constraints is to decompose the parameter b into
-- its base type and 'q' parameter, then use the same base type with a *different*
-- `q` parameter for the answer
g :: (b ~ bBase q1, b' ~ bBase q2) => b m -> b' m
instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where
g (D2 q) = D2 $ fromIntegral q -- LINE 1
错误
Could not deduce (bBase ~ D2 t0) (LINE 1)
该计划的结果
当我编写实例时,我当然打算使用bBase ~ D2 t
。我想t不会被约束(因此引入了t0),我不知道GHC是否可以解构这种类型。或者,也许我只是在做一些愚蠢的事情。
更重要的是,如果我将Bar的参数设置为* - > * - > *,那么这种类型的类型/类型解构就没有必要了。但我不能强制约束富:
class (Foo (b q)) => Bar b where -- b has kind * -> * -> *
g :: b q m -> q b' -- this signature is now quite simple, and I would have no problem implementing it
这不会起作用,因为q是不是酒吧的参数,我不希望它的参数吧。
我发现使用两个额外的“虚拟”相关类型的解决方案,但我真的不喜欢让他们身边,如果我不需要他们:
class (Foo b, b ~ (BBase b) (BMod b)) => Bar b where -- b has kind * -> *
type BBase b :: * -> * -> *
type BMod b :: *
g :: (Qux (BMod b), Qux q') => b m -> (BBase b) q' m
instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where
type BBase (D2 t q) = D2 t
type BMod (D2 t q) = q
g (D2 q) = D2 $ fromIntegral q
这工作,但它相当于明确解构类型,我认为这种类型的实例应该是不必要的。
我正在寻找一种解决方案:或者告诉我如何在“更多应用”类型上强制执行类约束,或告诉我如何使GHC解构类型。
谢谢!
我得到的完整错误信息是'amy16.hs:7:1: 非法等式约束b〜bBase q1 (使用-XGADT或-XTypeFamilies来允许这样做) 当检查类方法时: g :: forall(bBase :: * - > * - > *)q1(b':: * - > *)q2 m。 (b〜bBase q1,b'〜bBase q2)=> bm - > b'm 在Bar'的类声明中 Failed,modules loaded:none.'所以我认为你需要添加' GADTs“语言杂注或”TypeFamilies“杂注,以及其他一些编译指示。 – mhwombat
我没有在上面的代码中包含编译标志/语言编译指示,但当然我在这些术语中使用了我需要的所有东西(应该使所有的代码片段都能正常工作):TypeFamilies,FlexibleContexts,UndecidableInstances,TypeOperators,DataKinds ,ConstraintKinds,FlexibleInstances – crockeea