【问题标题】:How to make constraints of class function depends from class instance?如何使类函数的约束取决于类实例?
【发布时间】:2015-03-17 08:00:03
【问题描述】:

我一直在尝试为可以不同索引的列表实现包装器。

此类包装器的基本类:

class List l where
  toList :: l a -> [a]

支持索引的包装器:

class Indexed l where
  indexed :: (Ix i, List (l i)) => l i a -> [(i, a)]
  -- i - type of index
  -- l - type of wrapper

可以通过Integral类型索引的列表的包装器:

data IdxByIntList i a = (Ix i, Integral i) => IdxByIntList { getList :: [a] }

如果IdxByIntListList 的实例,那么iIntegralIx

instance (Integral i, Ix i) => List (IdxByIntList i) where
  toList = getList

看起来indexed 函数中的约束(Ix i, Integral i) 已满足,并且可以使IdxByIntList 成为Indexed 的实例:

instance Indexed IdxByIntList where
  indexed = zip [0..] . getList

但是不能编译,因为编译器不能推导 将变量 i 键入为 EnumNum 的实例。

编辑:

indexed 中,对于IdxByIntList[0..] 具有约束(Num a, Enum a),它转到zip [0..],依此类推,它转到indexed。所以,indexed 应该有约束 (Ix i, Enum i, Num i, List (l i)) 但它不是。

iIntegral 的实例,所以它是NumEnum 的实例。

我希望 Indexed 对其所有实例都有一般约束,并且 具有取决于具体实例的附加约束。在这里,我希望IdxByIntListindexed 上有约束(Ix i, List (l i), Integral i)。我该怎么做?

【问题讨论】:

  • 不要对构造函数施加约束。
  • 如果您将Integral i 添加到indexed 的约束中,它会起作用,尽管这可能不是您想要的。问题是(我认为)indexed 需要与所有(Ix i, List (l i)) 一起使用,但您正试图使其与(Ix i, Integral i, List (l i)) 一起使用。
  • @Cubic,它可以帮助我切断IdxByIntList 的实例,其中i 不是IntegralIx。我为什么要避免它?
  • @bheklilr,是的,看起来你是对的。我想我找到了答案。 [0..] 有约束 (Num a, Enum a)zip [0..] 等等,它去indexed。所以,indexed 应该有约束 (Ix i, Enum i, Num i, List (l i)) 但它不是。这就是它无法编译的原因。
  • 您可以使用enumerate = go 0 where go i [] = []; go i (x:xs) = (i, x) : go (i + 1) xs 减少限制。这只会将Num 的约束放在您的索引上。

标签: haskell types


【解决方案1】:

把类改一下怎么样

{-# LANGUAGE TypeFamilies #-}

import Data.Ix

class Indexed li where
  indexed :: li ~ l i => li a -> [(i, a)]
  -- i - type of index
  -- l - type of wrapper

data IdxByIntList i a = IdxByIntList { getList :: [a] }

instance (Integral i, Ix i) => Indexed (IdxByIntList i) where
  indexed = zip [0..] . getList

这使得类参数被应用l i 而不仅仅是l,这可能已经足够你使用了。

如果您真的确实需要在l 上对实例进行参数化,那么事情会变得更加棘手;我认为你需要一个类型为* -> Constraint 的关联类型族,它需要ConstraintKinds 扩展,当涉及多个类约束时,表达族实例会变得很尴尬。 (我不知道它在实践中是否令人满意。)

【讨论】:

    猜你喜欢
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-15
    • 2014-10-02
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 2012-09-06
    相关资源
    最近更新 更多