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

Cod*_*ein 2 haskell types class

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

class Dictionary d where
  lookupIn :: d -> Word -> String
Run Code Online (Sandbox Code Playgroud)

我想创建一个名为的变量runs并使其成为类型,Dictionary以便我可以在lookupIn函数中使用它.然而,没有任何工作.我试过了type runs = Dictionary,甚至data runs = Dictionary没有任何工作.

zw3*_*324 6

Haskell 不是面向对象的语言.类型类不是类.变量不是"变量"(虽然这在这里是无关紧要的),当然也不是一个对象.

看这篇文章.

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


Owe*_*wen 5

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

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

instance Dictionary () where
    lookupIn _ _ = "no"
Run Code Online (Sandbox Code Playgroud)

然后使用它:

main = do
    putStrLn $ lookupIn () "hello"
Run Code Online (Sandbox Code Playgroud)

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

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

thisInstance :: Dictionary ()
thisInstance = ???
Run Code Online (Sandbox Code Playgroud)

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


当然,有可能实现相同类型的行为,而不是使用类型类 - 记录适用于此:

data DictionaryType d = DictionaryData { lookupIn :: d -> Word -> String }
Run Code Online (Sandbox Code Playgroud)

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

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

main = do
    putStrLn $ lookupIn myDictionary () "hello"
Run Code Online (Sandbox Code Playgroud)

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