繁体   English   中英

使用RankNTypes和TypeFamilies的非法多态或限定类型

[英]Illegal polymorphic or qualified type using RankNTypes and TypeFamilies

我一直在慢慢地将llvm包移植到使用数据种类,类型族和type-nats,并在尝试通过引入新的Value类型来删除用于分类值的两个新类型( ConstValueValue )时遇到了一个小问题由constness参数化。

CallArgs只接受Value 'Variable a参数,并提供一个函数,用于将Value 'Const a转换为Value 'Variable a 我想概括CallArgs以允许每个参数为'Const'Variable 是否可以使用类型系列以某种方式对此进行编码? 我认为这可能与fundeps有关。

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}

data Const = Const | Variable

data Value (c :: Const) (a :: *)

type family CallArgs a :: * 
type instance CallArgs (a -> b) = forall (c :: Const) . Value c a -> CallArgs b
type instance CallArgs (IO a)   = IO (Value 'Variable a)

...无法编译:

/tmp/blah.hs:10:1:
    Illegal polymorphic or qualified type:
      forall (c :: Const). Value c a
    In the type instance declaration for `CallArgs'

以下解决方案的工作原理(相当于遗留代码),但要求用户强制转换每个常Value

type family CallArgs' a :: * 
type instance CallArgs' (a -> b) = Value 'Variable a -> CallArgs' b
type instance CallArgs' (IO a)   = IO (Value 'Variable a)

你要求的CallArgs有点像一个非确定性函数,它接受a -> b并返回Value 'Const a -> blahValue 'Variable a -> blah 有时你可以用非确定性函数来翻转它们; 实际上,这个具有确定性的逆。

type family   UnCallArgs a
type instance UnCallArgs (Value c a -> b) = a -> UnCallArgs b
type instance UnCallArgs (IO 'Variable a) = IO a

现在,你可以写任何类型的类型

foo :: CallArgs t -> LLVM t

或类似的东西,你可以写这个:

foo :: t -> LLVM (UnCallArgs t)

当然,您可能希望选择一个比UnCallArgs更好的名称,可能是Native或类似的东西,但这样做很好需要一些我没有的领域知识。

将包裹forall c。 在一个newtype AV为你工作?

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}

data CV = Const | Variable

data Value (c :: CV) (a :: *)

data AV a = AV (forall c. Value c a)

type family CallArgs a :: * 
type instance CallArgs (a -> b) = AV a -> CallArgs b
type instance CallArgs (IO a)   = IO (Value 'Variable a)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM