基本 Haskell 单态/多态问题 (HList)
我是 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
I'm a Haskell and a Stackoverflow noob, and here's my
first & probably quite basic Haskell question.
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
This makes sense, even if r1 & r2 are polymorphic in r
rPair aligns their r type in accordance with the type
signature. Is there a technical term for this 'alignment'?
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)
rCons works great if the R's passed are monomorphic in r,
constraining the list's r type as desired. but if they
are polymorphic in r it does not align them the way rPair
does, and gives an error (defining rc above).
No instance for (RList r (HCons (R r1 Double) HNil))
I have a vague intuition as to why this is the case, but
my question is in two parts. Could somebody clearly explain
the phenomenon? How would I write an rCons such that the
following would hold?
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)
Thanks,
_c
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
要回答第二个问题,您可以使用类型等效约束(来自 TypeFamilies 扩展)来放宽您的
RList
实例定义:现在您的
rc
将被推断为所需的类型。我认为我无法“清楚地解释”这种现象(肯定有人会),但很明显,rPair 和 rCons 之间的区别在于,前者绑定两个参数的
r
类型为同一类型变量,后者则不然:第二个参数只是l
约束,应该有一些RList 实例
表示l
)。由于rc
没有类型签名(请注意,如果您提供原始示例类型检查),并且 r1 和 r2 具有多态性,不等价,r 的,编译器正在尝试查找
RList r (HCons (R r1 Double) HNil)
的实例定义(r
来自第一个参数,r1
- 从第二个开始)并且未能这样做。通过类型等效约束,我们定义了一个具有两个不同的
r1
和r2
的 RList 实例,唯一的条件是它们需要等效,因此看起来 GHC 将它们绑定到解析l
的RList
实例时相同的多态类型变量。To answer your second question, you can use type equivalence constraint (from TypeFamilies extension) to relax your
RList
instance definition:Now your
rc
will be inferred to the desired type.I don't think I can 'clearly explain' the phenomenon though (somebody surely will), but it's obvious that the difference between
rPair
andrCons
is that while the former bindsr
type of both arguments to the same type variable, the later doesn't: the second argument is justl
constrained with that there should be some instance ofRList
for thatl
). Since there is no type signature forrc
(note that if you provide one your original example typechecks) and r1 and r2 have polymorphic, not equivalent,r
's , compiler is trying to find an instance definition forRList r (HCons (R r1 Double) HNil)
(r
comes from the 1st argument andr1
- from the 2nd) and fails to do so.With type equivalence constraint we define an instance of RList with two distinct
r1
andr2
with the only condition that these needs to be equivalent, so it looks like GHC binds them to the same polymorphic type variable when resolving instance ofRList
forl
.