Haskell 嵌套元组链上的多态函数

Haskell 嵌套元组链上的多态函数,haskell,fold,type-level-computation,Haskell,Fold,Type Level Computation,假设我有一个类型列表,类型为[*]: let Ts = '[Int, Bool, Char] 我想将其转换为元组链: type family Tupled (ts :: [*]) z :: * type instance Tupled (t ': ts) z = (t, Tupled ts z) type instance Tupled '[] z = z 到目前为止一切顺利: > :kind! Tupled Ts () Tupled Ts () :: * = (Int, (Bool,

假设我有一个类型列表,类型为
[*]

let Ts = '[Int, Bool, Char]
我想将其转换为元组链:

type family Tupled (ts :: [*]) z :: *
type instance Tupled (t ': ts) z = (t, Tupled ts z)
type instance Tupled '[] z = z
到目前为止一切顺利:

> :kind! Tupled Ts ()
Tupled Ts () :: *
= (Int, (Bool, (Char, ())))
现在,我希望能够编写一个类型
Fun
,以表示此链“底部”的多态函数。例如,
Fun Ts
应适用于以下任一类型:

(Int, (Bool, (Char, (String, ()))))
(Int, (Bool, (Char, (Word, (ByteString, ())))))
我试过这个:

newtype Fun as bs = Fun
  { unfun :: forall z. Tupled as z -> Tupled bs z }
但它没有进行打字检查:

Couldn't match type ‘Tupled bs z’ with ‘Tupled bs z0’
NB: ‘Tupled’ is a type function, and may not be injective
The type variable ‘z0’ is ambiguous
Expected type: Tupled as z -> Tupled bs z
  Actual type: Tupled as z0 -> Tupled bs z0
In the ambiguity check for the type of the constructor ‘Fun’:
  Fun :: forall z. Tupled as z -> Tupled bs z
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the definition of data constructor ‘Fun’
In the newtype declaration for ‘Fun’
我看到了使用数据族来避免注入性问题的建议:

data family Tupled (ts :: [*]) z :: *
data instance Tupled (t ': ts) z = Cons t (Tupled ts z)
data instance Tupled '[] z = Nil
确实,这让
编译变得有趣,但这似乎让我在使用元组时陷入了
Cons
Nil
的困境,如下所示:

Fun $ \ (i, (b, (c, z))) -> (succ i, (not b, (pred c, z)))

我可以设法解决这个问题吗?

启用
AllowAmbiguousTypes
。在GHC 8中,歧义检查是完全多余的,因为任何(基本上可解决的)歧义都可以通过类型应用程序解决。此外,您的案例似乎只是模糊性检查的假阳性,因为即使没有类型应用程序,我们也可以清楚地使用
Fun

我应该在问题中指出这一点,但启用这一点似乎没有什么区别——我收到了相同的错误消息。我使用的是来自
lts-8.9
Stack解析器的GHC 8.0.2。GHC 8.0.1和8.0.2都接受这一点。我不确定你那边出了什么问题(还有,我在那里使用了封闭式Family,但开放式也可以)。啊哈,
newtype Fun as bs=Fun(forall z…)
typechecks,但
=Fun{unfun::forall z…}
没有。我很困惑,因为
unfun
的定义被认为是一个模棱两可的使用站点。使其成为一个单独的函数,并使用类型应用程序
unfun::forall作为bs z。有趣的bs->元组化的bs z->元组化的bs z;unfun(Fun f)as=f@z as
解决了这个问题。谢谢你帮我解决这个问题。:)为什么不
键入Fun作为bs=forall z。Tupled as z->Tupled bs z
?@李耀霞:我希望能够将
Fun
作为参数传递给
Fun
,因此我需要
newtype
来隐藏不可指示性。