在Haskell中,你能创建一个类的对象吗?

时间:2013-03-07 22:55:59

标签: class haskell types

在我正在尝试调试的Haskell程序中,定义了一个类:

class Dictionary d where
  lookupIn :: d -> Word -> String

我想创建一个名为runs的变量并使其类型为Dictionary,因此我可以在lookupIn函数中使用它。然而,没有任何工作。我尝试了type runs = Dictionary,甚至data runs = Dictionary,但没有任何效果。

3 个答案:

答案 0 :(得分:6)

Haskell 不是面向对象的语言。类型类不是类。变量不是“变量”(尽管这里不相关),当然也不是对象。

请参阅此post

P.S。我想这是功课。尝试首先学习语言(甚至一点点),Haskell很可能比你想象的更有趣。

答案 1 :(得分:5)

在Haskell中,这是不可能的。在其他语言中可以使用类似类的构造(Scala,Agda),但在Haskell中是不可能的。

可以在Haskell中创建一个类的实例:

instance Dictionary () where
    lookupIn _ _ = "no"

然后使用它:

main = do
    putStrLn $ lookupIn () "hello"

确实,实例的行为与数据非常相似 - 它们在运行时由数据表示。这就是为什么在其他语言中,您可以将实例存储在变量中,并明确地传递它们。

但是,在Haskell中,无法命名实例或将其存储在变量中。也就是说,你不能这样做,或类似的东西:

thisInstance :: Dictionary ()
thisInstance = ???

原因是在Haskell中,假设对于每个类型和类型类,只有该类型的一个实例应用于该类型。也就是说,您只能定义一个instance Dictionary ()。由于只能有一个,因此命名它没有意义。这对Haskell的类型推断很方便 - 任何需要的实例都可以拉到当前函数的“参数”(实际上是类型类约束)。


当然可以实现相同类型的行为,而不是使用类型类 - 记录可以很好地用于此:

data DictionaryType d = DictionaryData { lookupIn :: d -> Word -> String }

现在lookupIn的类型为DictionaryType d -> d -> Word -> String,它是类型类使用类型(Dictionary d) => d -> Word -> String的字面翻译。你可以像这样使用它:

myDictionary :: DictionaryType ()
myDictionary = DictionaryData (\_ _ -> "no")

main = do
    putStrLn $ lookupIn myDictionary () "hello"

与类型类解决方案在功能上完全相同,唯一的区别是语法和类型检查的工作方式。

答案 2 :(得分:0)

想到它的一种方法是:

在OO语言中,类定义了类型(即一组潜在值)和一组其他类型(即潜在后代类)。

在Haskell中,类型类仅定义 一组类型(即类型类的潜在“实例”)。类型类本身不是类型。

(实际上,我在集合和类之间滑过distinction in set theory,这就是为什么它们被称为“ typeclass”而不是“ typeset”的原因。但这在这里并不重要。)