在 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"
在功能上与类型类解决方案相同,唯一的区别是语法和类型检查的工作方式。