MK
Size: a a a
MK
AV
AV
MK
MK
MK
MK
к
R
data Some f = forall a. Some (f a)
data TyNameRep (kind :: GHC.Type) = TyNameRep Symbol Nat
class KnownPolytype (binds :: [Some TyNameRep]) term args res a | args res -> a, a -> res where
knownPolytype :: Proxy binds -> TypeScheme term args res
instance (KnownSymbol name, KnownNat uniq, KnownKind kind, KnownPolytype binds term args res a) =>
KnownPolytype ('Some ('TyNameRep @kind name uniq) ': binds) term args res a where
knownPolytype _ = TypeSchemeAll @name @uniq @kind Proxy $ \_ -> knownPolytype (Proxy @binds)
KnownPolytype по сути определен "рекурсией" по первому аргументу типа [Some TyNameRep], где Some экзистенциально упаковывает кайнд. Так вот в инстансе мы матчим по 'Some и хаскель позволяет достать kind через тайп-левельный тайп-апликейшон и даже позволяет сделать по этому kind констрейт KnownKind (кастомный класс, не из бейз). То есть мы сначала упаковали в экзистенциальный тип, а потом распаковали и используем экзистенциальную переменную в вычислениях. На уровне значений пришлось бы упаковывать переменную вместе с констрейнтом, иначе когда ее оттуда достаешь, все информация потеряна и ничего о переменной уже сказать нельзяMK
data Some f = forall a. Some (f a)
data TyNameRep (kind :: GHC.Type) = TyNameRep Symbol Nat
class KnownPolytype (binds :: [Some TyNameRep]) term args res a | args res -> a, a -> res where
knownPolytype :: Proxy binds -> TypeScheme term args res
instance (KnownSymbol name, KnownNat uniq, KnownKind kind, KnownPolytype binds term args res a) =>
KnownPolytype ('Some ('TyNameRep @kind name uniq) ': binds) term args res a where
knownPolytype _ = TypeSchemeAll @name @uniq @kind Proxy $ \_ -> knownPolytype (Proxy @binds)
KnownPolytype по сути определен "рекурсией" по первому аргументу типа [Some TyNameRep], где Some экзистенциально упаковывает кайнд. Так вот в инстансе мы матчим по 'Some и хаскель позволяет достать kind через тайп-левельный тайп-апликейшон и даже позволяет сделать по этому kind констрейт KnownKind (кастомный класс, не из бейз). То есть мы сначала упаковали в экзистенциальный тип, а потом распаковали и используем экзистенциальную переменную в вычислениях. На уровне значений пришлось бы упаковывать переменную вместе с констрейнтом, иначе когда ее оттуда достаешь, все информация потеряна и ничего о переменной уже сказать нельзяAV
AV
AV
MK
MK