5

我正在以下程序中编写一个简单的哈希树结构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 ) )

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

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

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

谢谢

4

1 回答 1

8

Haskell 中常见的“陷阱”之一是,如果您将类约束放在data声明中,则使用该类型的每个函数也必须具有类约束。出于这个原因,您的data声明在 Haskell 中不是惯用的,您应该消除它的类约束。data无论如何,在声明中声明类约束对您没有任何好处。

基本上,函数类型必须重复类约束。该函数的用户如何知道他们必须使用相关类的实例?请注意,您可以根据根据您的类型定义的函数定义的函数定义f函数,这样根本没有提及您的类型,但是由于类型依赖性,它需要一个类型的参数间接并最终用作您类型的第一个参数。 的类型必须具有类约束,Haskell 正确地推断出来,如果缺少类型注释,它将拒绝您的类型注释。ghHashTable a bfHashTableaHashTablef

于 2012-06-25T16:30:37.500 回答