如何为另一个类型类中的所有类型编写实例?

pen*_*ope 10 haskell

我必须定义一个类型类,它Truthy包含一个true将类型类的实例转换为Bool值的方法.

我的类型类声明:

class Truthy a where
    true :: a -> Bool
Run Code Online (Sandbox Code Playgroud)

接下来,我必须为各种类型定义此类的实例,包括列表和数字类型.我已经为list和Ints 做过了,但有没有办法一次为所有数字类型做到这一点?

基于我的Int声明:

instance Truthy Int where
    true = (/=) 0
Run Code Online (Sandbox Code Playgroud)

我已经尝试添加类型类约束,但它不起作用:

instance (Num a) => (Truthy a) where
    true = (/=) 0::a
Run Code Online (Sandbox Code Playgroud)

如果有一种方法与我的想法相似,或者我应该分别为每种数字类型定义它?

Tik*_*vis 10

这可能对家庭作业没有帮助,但你实际上可以写出这样的声明.你只需启用-XFlexibleInstances即可.至少在GHC中,您可以通过在文件顶部放置一个pragma来完成此操作:

{-# LANGUAGE FlexibleInstances #-}
Run Code Online (Sandbox Code Playgroud)

如果你仔细查看你得到的错误消息,它会说"如果你想禁用它,请使用-XFlexibleInstances.".

在这种特殊情况下,您还需要启用UndecidableInstancesOverlappingInstances:

 {-# LANGUAGE FlexibleInstances,  UndecidableInstances, OverlappingInstances #-}
Run Code Online (Sandbox Code Playgroud)

您需要,FlexibleInstances因为标准Haskell不允许任何形式的实例,其中类型变量在头部中出现多次.这完全没问题 - 我是最常用的扩展之一(根据这个问题).

您需要,UndecidableInstances因为您的实例声明可能会导致类型检查器永远循环.我认为使用UndecidableInstances可以通过限制尝试减少实例时检查的深度来防止这种情况.这通常 - 包括在这种情况下 - 很好,但理论上可以使特定程序是否通过类型检查实现依赖.不过,它应该适用于你的情况.

正如hammar指出的那样,您需要启用,OverlappingInstances因为在检查实例是否重叠时会忽略实例的"上下文" .Num a在这种情况下,背景是有点的.因此,实例 - 用于检查它是否重叠 - 被读取instance Truthy a...并与所有内容重叠.与OverlappingInstances启用,你只需要有一个实例,它是最具体的这个工作.

  • 如果您想要除数字之外的任何实例,您还需要`OverlappingInstances`,因为它与所有实例重叠.这是因为实例头是"a",它匹配任何东西.直到之后才检查`Num`约束. (3认同)
  • @TikhonJelvis:定义实例很好,但你是否尝试过实际使用它们? (2认同)