Следующий код не компилировать:Невозможно создать тип-полиморфные типы
{-# 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 считает, что все виды совпадают, но он просто отказывается заменить полиморфный тип args :: (*,*)
на '(b0,b0)
. Другими словами, я думаю, что это своего рода полиморфный эквивалент GHC жалуясь Could not deduce a ~ Int
в этом вполне допустимо, например:
f :: (Num a) => a -> a
f = undefined
g = f (3 :: Int)
Любые предложения?
К сожалению, 'args :: (,) * *' не означает, что 'args = '(a, b)' для некоторых 'a' и' b', поэтому экземпляр типа CtxOf BasicCtxD' (a, b) = (a ~ b) ', как известно, не применяется. (... и поэтому 'g' не может быть задан тип как полиморфный, как требовалось' runAll', даже если вы 'wrap1Arg'.) –
Я думаю, что эта ошибка совершенно верна - только потому, что' args :: (a, b) 'существует, не означает, что' существует (q :: a) (r :: b). args ~ '(a, r) ', потому что система типа Haskells явно противоречива - тривиально, мы имеем' Any :: (*, *) '. Измените '... (CtxOf ctx args) => Прокси args -> ...' to '(CtxOf ctx args) => Sing args -> ...', а затем вы можете сопоставить шаблон по singleton, который * делает * содержат доказательство того, что 'args :: (a, b) ==> существует (q :: a) (r :: b). args ~ '(a, r) '. – user2407038
@ Даниэль Вагнер Хм, вижу. И нет способа определить семейный экземпляр как нечто более похожее на 'type instance CtxOf BasicCtxD (arg :: (*, *)) = (arg ~ '(a, b), (a ~ b))', правильно? (То, что дает «' a' и 'b', не имеет значения»). – crockeea