Haskell:难以将上下文(Eq a)嵌入到数据声明中

Gab*_*elG 6 haskell

我在以下程序中编写一个简单的哈希树结构hash_lookup.hs:

module Main where

    data (Eq a) => HashTable a b = HashChildren (a, [HashTable a b]) | Hash (a, b) deriving (Show)

    getKey :: HashTable a b -> a

    getKey (HashChildren (k, hs)) = k
    getKey (Hash (k, h)) = k

    lookUp :: [a] -> HashTable a b -> Maybe (HashTable a b)

    lookUp [] table = return table
    lookUp _ (Hash _) = Nothing
    lookUp (p:path) (HashChildren (_, ts) ) = lookUp path ( head ( dropWhile (\x -> (getKey x) /= p) ts ) )
Run Code Online (Sandbox Code Playgroud)

getKey用于检索给定HashTable的根密钥,lookUp采用字符串列表,并且意味着遵循它找到的第一个路径,直到它到达完整路径或失败(我知道这不是自然的树的行为,但这是我的教程想要的).

我有两个问题:1)为什么我得到一条错误消息,告诉我a /= a(从最后一行)不允许No instance for (Eq a)(因为终端中的错误消息),尽管(Eq a)在数据声明中?

2)除了我得到的错误和查找功能看似奇怪的行为,这是好的还是惯用的 Haskell?

谢谢

Lui*_*las 8

Haskell中常见的"陷阱"之一是,如果将类约束放在data声明上,那么使用该类型的每个函数也必须具有类约束.出于这个原因,你的data声明在Haskell中不是惯用的,你应该消除它的类约束.data无论如何,它都没有在声明中声明类约束.

基本上,函数类型必须重复类约束.该函数的用户如何知道他们必须使用相关类的实例?注意,你可以有一个功能,f在功能方面定义g在一个定义的h是在你来定义的HashTable a b类型,这样f没有提到你的HashTable类型可言,因为类型的依赖性却需要类型的参数a是间接并最终用作您的HashTable类型的第一个参数. f的类型必须具有类约束,Haskell正确推断,如果缺少类型注释,它将拒绝您的类型注释.