【问题标题】:Declare list instance of a type class声明类型类的列表实例
【发布时间】:2017-01-10 13:27:37
【问题描述】:

我正在通过UPENN Haskell lecture notes 学习 Haskell 类型类,用示例代码制作我自己的类型类:

class Listable a where
    toList :: a -> [Int]

instance Listable Int where
    toList x = [x]

instance Listable Bool where
    toList True  = [1]
    toList False = [0]

它适用于IntBool,但是当我添加[Int] 的实例时ghci 失败:

instance Listable [Int] where
    toList = id

错误:

‘Listable [Int]’的非法实例声明

(所有实例类型必须为 (T a1 ... an) 形式

其中 a1 ... an 是不同类型的变量

并且每个类型变量在实例头部最多出现一次。

如果您想禁用此功能,请使用 FlexibleInstances。)

在“Listable [Int]”的实例声明中

我尝试了几次,但都失败了:

toList x = id x
toList x = x
toList = \x -> x

我该如何解决?

【问题讨论】:

  • 您是否注意到错误中指出Use FlexibleInstances if you want to disable this 的部分? Plain Haskell 是相当严格的,尤其是在类型类中;大多数现代程序都使用多个扩展,因此现在编译器通常会建议您需要打开哪个扩展。
  • @chi 是的,但我想ghci 想让我用FlexibleInstances 替换关键字instance,这被证明是假的。
  • 啊,我明白了 :) 扩展功能已启用,如下面的答案所示。
  • 你可以让它更通用:instance Foldable t => Listable (t Int) where toList = Data.Foldable.toList

标签: haskell types typeclass


【解决方案1】:

只需在源文件顶部添加以下行

{-# LANGUAGE FlexibleInstances #-}

这将启用此表单的实例声明所需的 FlexibleInstances 扩展,因为 Haskell 98 不允许它们。

请注意,您还可以通过在调用 ghcghci 时添加 -XFlexibleInstances 标志来启用扩展,但这样做被认为是一种不好的做法,因为它会为所有模块启用扩展。这也意味着您的程序只能根据传递给编译器的命令行标志成功编译。这就是为什么最好按照我上面解释的那样在每个模块的基础上启用扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-09
    • 2011-08-11
    • 1970-01-01
    • 2018-03-08
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多