4

我是 Haskell 和 Stackoverflow 菜鸟,这是我的第一个可能非常基本的 Haskell 问题。

module M where

import Data.HList

data R r a 

r1 = undefined :: R a Int
r2 = undefined :: R a Double

rPair :: R r a -> R r b -> (R r a, R r b)
rPair = (,)

rp = rPair r1 r2

这是有道理的,即使 r1 和 r2 在 r 中是多态的,rPair 也会根据类型签名对齐它们的 r 类型。这种“对齐”是否有技术术语?

class HList l => RList r l
instance RList r HNil
instance RList r l => RList r (HCons (R r a) l)

rCons :: RList r l => R r a -> l -> (HCons (R r a) l)
rCons = hCons

rc = rCons r1 (rCons r2 hNil)

如果传递的 R 在 r 中是单态的,则 rCons 效果很好,可以根据需要限制列表的 r 类型。但如果它们在 r 中是多态的,它不会像 rPair 那样对齐它们,并给出错误(在上面定义 rc)。

No instance for (RList r (HCons (R r1 Double) HNil))

我对为什么会这样有一个模糊的直觉,但我的问题分为两部分。有人可以清楚地解释这种现象吗?我将如何编写一个 rCons 以使以下内容成立?

r1 = undefined :: R a Int
r2 = undefined :: R a Double

rc :: HCons (R a Int) (HCons (R a Double) HNil)
rc = rCons r1 (rCons r2 hNil)

谢谢,_c

4

1 回答 1

1

要回答您的第二个问题,您可以使用类型等价约束(来自 TypeFamilies 扩展)来放宽您的RList实例定义:

class HList l => RList r l
instance RList r HNil
instance (RList r1 l, r1 ~ r2) => RList r1 (HCons (R r2 a) l)

现在您rc将被推断为所需的类型。

我认为我不能“清楚地解释”这种现象(肯定有人会),但很明显,和之间的区别在于rPairrCons虽然前者将r两个参数的类型绑定到同一个类型变量,但后者不会:第二个参数只是l受限于应该有一些RListfor that的实例l)。由于没有类型签名 for rc(请注意,如果您提供一个原始示例类型检查)并且 r1 和 r2 具有多态性,而不是等效的, r's ,编译器正在尝试为RList r (HCons (R r1 Double) HNil)(r来自第一个参数和r1- 从 2 日开始)并且没有这样做。使用类型等价约束,我们定义了一个具有两个不同的 RList 实例,r1并且r2唯一的条件是它们需要等价,因此看起来 GHC 在解析RListfor 的实例时将它们绑定到相同的多态类型变量l

于 2011-03-05T02:49:45.333 回答