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 は文字列のリストを取得し、最初に見つけたパスをフル パスに到達するか失敗するまでたどることを意図しています (これは自然ではないことは承知しています)。ツリーの動作ですが、それは私のチュートリアルが望んでいるものです)。

2 つの質問があります。1)データ宣言にあるにもかかわらず、(ターミナルのエラー メッセージ) があるのに (a /= a最終行から) 許可されていないというエラー メッセージが表示されるのはなぜですか?No instance for (Eq a)(Eq a)

2)私が得ているエラーとルックアップ関数の一見奇妙な動作以外に、これは良いHaskellですか、それとも慣用的なHaskellですか?

ありがとう

4

1 に答える 1

8

Haskell の一般的な「落とし穴」の 1 つは、data宣言にクラス制約を設定する場合、その型を使用するすべての関数にもクラス制約が必要であるということです。このため、data宣言は Haskell では慣用的ではなく、そのクラス制約を排除する必要があります。とにかく、宣言でクラス制約を宣言しても何も得られませdataん。

基本的に、関数型はクラス制約を繰り返さなければなりません。問題のクラスのインスタンスを使用する必要があることを関数のユーザーが知るには、他にどのような方法がありますか? 型に関して定義された an に関して定義されfた関数に関して定義された関数を持つことができることに注意してください。間接的かつ最終的には、型の最初のパラメーターとして使用されます。 の型にはクラス制約が必要であり、Haskell はそのように正しく推論し、型注釈が欠落している場合は拒否します。ghHashTable a bfHashTableaHashTablef

于 2012-06-25T16:30:37.500 に答える