无法实例化种类多态类型
Cannot instantiate kind-polymorphic types
以下代码编译失败:
{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances, KindSignatures,
MultiParamTypeClasses, PolyKinds, RankNTypes,
ScopedTypeVariables, TypeFamilies, TypeOperators #-}
import Data.Proxy
import GHC.Prim
type family CtxOf d (args :: k) :: Constraint
class Run ctx (params :: [k]) where
runAll :: Proxy ctx
-> Proxy params
-> (forall (args :: k) . (CtxOf ctx args) => Proxy args -> Bool)
-> [Bool]
instance Run ctx '[] where
runAll _ _ _ = []
data BasicCtxD
type instance CtxOf BasicCtxD '(a,b) = (a ~ b)
instance (Run BasicCtxD params, a ~ b)
=> Run BasicCtxD ( '(a,b) ': params) where
runAll pctx _ f = (f (Proxy::Proxy '(a,b))) :
(runAll pctx (Proxy::Proxy params) f)
wrap1Arg :: forall a b . (a ~ b)
=> (Proxy '(a,b) -> Bool) -> Proxy '(a,b) -> Bool
wrap1Arg f = f
map1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> [Bool]
map1Arg g = runAll (Proxy::Proxy BasicCtxD) (Proxy::Proxy '[ '(Int,Int)]) $ wrap1Arg g
有错误
Could not deduce ((~) ((,) * *) args '(b0, b0))
from the context (CtxOf ((,) * *) BasicCtxD args)
bound by a type expected by the context:
CtxOf ((,) * *) BasicCtxD args => Proxy ((,) * *) args -> Bool
at Main.hs:31:13-86
‘args’ is a rigid type variable bound by
a type expected by the context:
CtxOf ((,) * *) BasicCtxD args => Proxy ((,) * *) args -> Bool
at Main.hs:31:13
Expected type: Proxy ((,) * *) args -> Bool
Actual type: Proxy ((,) * *) '(b0, b0) -> Bool
In the second argument of ‘($)’, namely ‘wrap1Arg g’
In the expression:
runAll (Proxy :: Proxy BasicCtxD) (Proxy :: Proxy '['(Int, Int)]) $ wrap1Arg g
我怀疑,就像我刚刚提交的ticket一样,我只需要以正确的方式戳GHC。似乎 GHC 认为所有 种类 都匹配,但它只是拒绝用 '(b0,b0)
替换多态类型 args :: (*,*)
。换句话说,我认为在这个完全有效的例子中,它是 GHC 抱怨 Could not deduce a ~ Int
的一种多态等价物:
f :: (Num a) => a -> a
f = undefined
g = f (3 :: Int)
有什么建议吗?
多亏了评论,我找到了一个使用 GADT 来隐藏约束和可变参数数量的解决方案。
{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances, KindSignatures,
MultiParamTypeClasses, PolyKinds, RankNTypes, GADTs,
ScopedTypeVariables, TypeFamilies, TypeOperators #-}
import Data.Proxy
data family CtxOf ctx
class Run ctx (params :: [k]) where
runAll :: Proxy params
-> (CtxOf ctx -> Bool)
-> [Bool]
instance Run ctx '[] where
runAll _ _ = []
data BasicCtxD
data instance CtxOf BasicCtxD where BasicCtx :: (a ~ b) => Proxy '(a,b) -> CtxOf BasicCtxD
instance (Run BasicCtxD params, a ~ b)
=> Run BasicCtxD ( ('(a,b)) ': params) where
runAll _ f = (f $ BasicCtx (Proxy::Proxy '(a,b))) :
(runAll (Proxy::Proxy params) f)
wrap1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> CtxOf BasicCtxD -> Bool
wrap1Arg f (BasicCtx p) = f p
map1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> [Bool]
map1Arg g = runAll (Proxy::Proxy '[ '(Int,Int)]) $ wrap1Arg g
本质上,type 系列 CtxOf
变成了 data 系列。这个想法是使家族的每个实例成为一个 GADT,它持有一个约束(以前由类型家族定义),以及类型 pair/triple/etc.
中存在的类型。
以下代码编译失败:
{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances, KindSignatures,
MultiParamTypeClasses, PolyKinds, RankNTypes,
ScopedTypeVariables, TypeFamilies, TypeOperators #-}
import Data.Proxy
import GHC.Prim
type family CtxOf d (args :: k) :: Constraint
class Run ctx (params :: [k]) where
runAll :: Proxy ctx
-> Proxy params
-> (forall (args :: k) . (CtxOf ctx args) => Proxy args -> Bool)
-> [Bool]
instance Run ctx '[] where
runAll _ _ _ = []
data BasicCtxD
type instance CtxOf BasicCtxD '(a,b) = (a ~ b)
instance (Run BasicCtxD params, a ~ b)
=> Run BasicCtxD ( '(a,b) ': params) where
runAll pctx _ f = (f (Proxy::Proxy '(a,b))) :
(runAll pctx (Proxy::Proxy params) f)
wrap1Arg :: forall a b . (a ~ b)
=> (Proxy '(a,b) -> Bool) -> Proxy '(a,b) -> Bool
wrap1Arg f = f
map1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> [Bool]
map1Arg g = runAll (Proxy::Proxy BasicCtxD) (Proxy::Proxy '[ '(Int,Int)]) $ wrap1Arg g
有错误
Could not deduce ((~) ((,) * *) args '(b0, b0))
from the context (CtxOf ((,) * *) BasicCtxD args)
bound by a type expected by the context:
CtxOf ((,) * *) BasicCtxD args => Proxy ((,) * *) args -> Bool
at Main.hs:31:13-86
‘args’ is a rigid type variable bound by
a type expected by the context:
CtxOf ((,) * *) BasicCtxD args => Proxy ((,) * *) args -> Bool
at Main.hs:31:13
Expected type: Proxy ((,) * *) args -> Bool
Actual type: Proxy ((,) * *) '(b0, b0) -> Bool
In the second argument of ‘($)’, namely ‘wrap1Arg g’
In the expression:
runAll (Proxy :: Proxy BasicCtxD) (Proxy :: Proxy '['(Int, Int)]) $ wrap1Arg g
我怀疑,就像我刚刚提交的ticket一样,我只需要以正确的方式戳GHC。似乎 GHC 认为所有 种类 都匹配,但它只是拒绝用 '(b0,b0)
替换多态类型 args :: (*,*)
。换句话说,我认为在这个完全有效的例子中,它是 GHC 抱怨 Could not deduce a ~ Int
的一种多态等价物:
f :: (Num a) => a -> a
f = undefined
g = f (3 :: Int)
有什么建议吗?
多亏了评论,我找到了一个使用 GADT 来隐藏约束和可变参数数量的解决方案。
{-# LANGUAGE DataKinds, FlexibleContexts, FlexibleInstances, KindSignatures,
MultiParamTypeClasses, PolyKinds, RankNTypes, GADTs,
ScopedTypeVariables, TypeFamilies, TypeOperators #-}
import Data.Proxy
data family CtxOf ctx
class Run ctx (params :: [k]) where
runAll :: Proxy params
-> (CtxOf ctx -> Bool)
-> [Bool]
instance Run ctx '[] where
runAll _ _ = []
data BasicCtxD
data instance CtxOf BasicCtxD where BasicCtx :: (a ~ b) => Proxy '(a,b) -> CtxOf BasicCtxD
instance (Run BasicCtxD params, a ~ b)
=> Run BasicCtxD ( ('(a,b)) ': params) where
runAll _ f = (f $ BasicCtx (Proxy::Proxy '(a,b))) :
(runAll (Proxy::Proxy params) f)
wrap1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> CtxOf BasicCtxD -> Bool
wrap1Arg f (BasicCtx p) = f p
map1Arg :: (forall a (b :: k) . (a ~ b) => Proxy '(a,b) -> Bool) -> [Bool]
map1Arg g = runAll (Proxy::Proxy '[ '(Int,Int)]) $ wrap1Arg g
本质上,type 系列 CtxOf
变成了 data 系列。这个想法是使家族的每个实例成为一个 GADT,它持有一个约束(以前由类型家族定义),以及类型 pair/triple/etc.