【问题标题】:Non type-variable argument in the Constraint: Enum A => Ord A约束中的非类型变量参数:Enum A => Ord A
【发布时间】:2019-10-05 15:14:55
【问题描述】:

我是 Haskell 的新手。

我想使用 Enum 类为自定义数据类型实现 Ord 类。

如果我实现 Enum 类并在 Ord 所需的 compare 函数的实现中直接使用 fromEnum 函数,它工作正常 类。

但由于 类型签名类型级别约束 适用于 可读性文档。我想在 Enum 实例上指定我的自定义数据 dependsOrd 实例。 当我编写以下代码时,它会引发错误。

data DayOfWeek
  = Mon | Tue | Weds | Thu | Fri | Sat | Sun
  deriving (Eq, Show)    

instance Enum DayOfWeek => Ord DayOfWeek where
  compare a b = compare (fromEnum a) (fromEnum b)

instance Enum DayOfWeek where
  toEnum 1 = Mon
  toEnum 2 = Tue
  toEnum 3 = Weds
  toEnum 4 = Thu
  toEnum 5 = Fri
  toEnum 6 = Sat
  toEnum 7 = Sun

  fromEnum Mon = 1
  fromEnum Tue = 2
  fromEnum Weds = 3
  fromEnum Thu = 4
  fromEnum Fri = 5
  fromEnum Sat = 6
  fromEnum Sun = 7

错误

* Non type-variable argument in the constraint: Enum DayOfWeek
  (Use FlexibleContexts to permit this)
* In the context: Enum DayOfWeek
  While checking an instance declaration
  In the instance declaration for `Ord DayOfWeek'

我们可以在具体类型上写约束吗

【问题讨论】:

  • 先定义Enum 实例,然后定义Ord 实例会更简单。此外,需要 Enum 实例和简单地使用 定义Ord 实例之间存在区别。

标签: haskell typeclass


【解决方案1】:

如果我们启用一对扩展,您的代码就会编译,写入文件的第一行:

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}

不过,我认为这不值得。我会删除上下文,因为这是大多数现有代码所做的。

此外,我不确定您为什么认为记录一个实例依赖于另一个实例这一事实很重要。我认为这是一个实现细节,因此我想对用户隐藏,而不是指出来。

【讨论】:

  • 感谢您的帮助。什么是 FlexibleContexts,您能否推荐任何适合初学者学习 haskell 的网站。
  • @PKChem Haskell 最初是在 20 多年前设计的,因此它只能处理非常简单的情况,例如 instance C variable => C (T variable)。在这里,上下文C variable 确实需要variable 是一个类型变量。随着时间的推移,这个限制和许多其他限制都被取消了。默认情况下,GHC 仍然应用许多限制,但允许通过扩展删除大部分限制。现在的大多数代码都至少利用了一些扩展。灵活的上下文允许上述上下文中的非变量,例如instance C Char => ....
  • @PKChem 目前最适合初学者的教程似乎是LYAH,即使它不包括高级主题。 IMO,您的问题不是初学者级别,而是基于某些类型类技术性的。不要害怕阅读扩展名上的GHC docs。通常它是无法理解的,即使它有点技术性,并且经常带有示例。
猜你喜欢
  • 2020-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
相关资源
最近更新 更多