我应该使用类型类吗?

时间:2013-06-14 02:05:05

标签: haskell

我在使用时以及何时不在我的代码中使用类型类时遇到一些困难。我的意思是创建我自己的,而不是使用已经定义的类型类。通过示例(非常愚蠢的例子),我应该这样做:

data Cars = Brakes | Wheels | Engine
data Computers = Processor | RAM | HardDrive  

class Repairable a where
    is_reparaible :: a -> Bool

instance Repairable Cars where
    is_repairable (Brakes) = True
    is_repairable (Wheels) = False
    is_repairable (Engine) = False

instance Repairable Computers where
    is_repairable (Processor) = False
    is_repairable (RAM)       = False
    is_repairable (HardDrive) = True

checkState :: (Reparaible a) => a -> ... 
checkState a = ...

(显然,这是一个愚蠢的,不完整的例子)。

但这有点用处,不是吗?为什么我不应该做一些简单的事情,只定义函数而不定义新的数据类型和类型类(带有它们的实例)。

这个例子太简单了,但事实上,当我在github上浏览Haskell代码而不是仅定义函数时,我常常会看到类似的东西(新数据类型+类型类+实例)。

那么,当我应该创建新的数据类型,类型类等时,我应该何时使用函数?

感谢。

2 个答案:

答案 0 :(得分:44)

  

为什么我不应该做一些简单的事情而只是定义功能   没有定义新的数据类型和类型类(用他们的   实例)。

为什么呢?你可以定义:

checkState :: (a -> Bool) -> (a -> b) -> (a -> b) -> a -> b
checkState is_repairable repairs destroy a
    = if (is_repairable a) then repairs a else destroy a

人们一直滥用类型类。这并不意味着它是惯用的。

要回答更一般的问题,以下是关于何时使用类型类以及何时不使用它们的一些经验法则:

在以下情况下使用类型类:

  • 每种给定类型只有一种正确的行为

  • 类型类具有所有实例必须满足的关联方程式(即“法则”)

如果符合以下条件,请不要使用类型类:

  • 您正试图命名事物。这就是模块和名称空间的用途。

  • 使用您的类型类的人无法在不查看实例的源代码的情况下推断其行为方式

  • 您发现必须启用的扩展程序已失控

答案 1 :(得分:5)

您通常可以使用数据类型而不是类型类,例如

data Repairable a = Repairable 
   { getRepairable :: a
   , isRepairable :: Bool
   , canBeRepairedWith :: [Tool] -> Bool  -- just to give an example of a function
   } 

当然你需要明确地传递这个值,但如果你有多个选择,这可能是一件好事(例如,尽可能考虑SumProduct Monoid )。除了你的表现力或多或少与一个类型相同。