【问题标题】:Overlapping instance in haskellhaskell中的重叠实例
【发布时间】:2013-05-11 16:05:51
【问题描述】:

我正在阅读HList 库的代码。有一个HBetween 类,它是一个类型级函数,采用HNat n 并返回一个HNats 列表,形成一个范围[HZero,n)。我想实现另一个类HRange,它有一个重载函数hRange :: l -> u -> r,它采用下限l 和上限u,并返回一个范围[l, u)。我的代码如下(为了让代码更清晰,hRange 的结果是倒序的,比如 (u, l] )

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, 
    FlexibleInstances, FlexibleContexts, UndecidableInstances #-}
module Data.HList.HNats where
import Data.HList.CommonMain
class (HNat l, HNat u) => HRange l u r | l u -> r where
  hRange :: l -> u -> r
instance HNat l => HRange l (HSucc l) (HCons l HNil) where
  hRange _ _ = undefined
instance HRange l u r => HRange l (HSucc u) (HCons u r) where
  hRange _ _ = undefined

我在ghci中尝试了这段代码,发生了意想不到的事情:

*Data.HList.HNats Data.HList> :load Data/HList/HNats
[1 of 1] Compiling Data.HList.HNats ( Data/HList/HNats.hs, interpreted )
Ok, modules loaded: Data.HList.HNats.
*Data.HList.HNats Data.HList> hRange hZero (hSucc hZero )

<interactive>:24:1:
    Overlapping instances for HRange
                                HZero (HSucc HZero) (HCons HZero HNil)
      arising from a use of `hRange'
    Matching instances:
      instance HNat l => HRange l (HSucc l) (HCons l HNil)
        -- Defined at Data/HList/HNats.hs:14:10
      instance HRange l u r => HRange l (HSucc u) (HCons u r)
        -- Defined at Data/HList/HNats.hs:20:10
    In the expression: hRange hZero (hSucc hZero)
    In an equation for `it': it = hRange hZero (hSucc hZero)
*Data.HList.HNats Data.HList> 

我不知道为什么hRange hZero (hSucc hZero ) 可以匹配实例instance HRange l u r =&gt; HRange l (HSucc u) (HCons u r)。任何解释表示赞赏!

【问题讨论】:

    标签: haskell types metaprogramming


    【解决方案1】:

    请注意,GHC 将hRange hZero (hSucc hZero) 的类型指定为HRange HZero (HSucc HZero) (HCons Zero HNil)。因为 GHC 实例匹配器在选择匹配之前不考虑约束,它只检查 HRange l (HSucc u) (HCons u r)l 可以匹配任何东西,所以匹配HZeroHSucc u 明显匹配 HSucc HZeroHCons u rHCons HZero HNil 也是如此。

    一般而言,就 GHC 而言,您的第二个实例是第一个实例的严格超集,因为在选择实例时,右侧的唯一区别(因此忽略约束 HNat lHRange l u r)第一个是第二个,r 限制为HNil。解决这个问题的正常方法是加入一个幻像类型或类来区分右侧,尽管我不知道如何在这里做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2019-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多