2017-03-18 2 views
2

私のhaskellプログラムでは、[(key, value)]という形式のデータベースを表すリストがあります。たとえば、有効なデータベースは[("key1", "value1"), ("key2", "value2"), ("key3", "value3")]です。 キーのデータは、常に文字列となります。2入力での関数のオーバーロードの読み込み

私の質問は:read dbList "key1":それは、読み取り機能をオーバーロードし、このようにそれを使用することにより読み出し動作をコーディングすることは可能でしょうか?はいの場合、どうすればこの問題を解決できますか?出力は("not found","value data for key not exists")または("found", "value1")である必要があります。

私はこれをどのように解決することができますが、私が見つけたのは、ある入力パラメータに読み込み関数を使用する方法と、その特定の型の読み込みのインスタンスを作成するために新しい型を定義する方法ですそれが必要とされています。しかし、2つの入力パラメタで読み込み関数を何とかオーバーロードすることができれば、私はまだ不思議です。

+0

'read :: Read a => String - > a'は、文字列表現から特定の型の値を作成するためのものであり、データベースの参照を行うものではありません。 – chepner

+0

ご意見ありがとうございます。私の上司は私に** read **関数を使用してコード例を期待していましたが、解決できる方法が見つからないため、これが可能かどうか確かめたいと思っていました。 –

+0

彼は 'Read'クラスを知っていますか? 'read'クラス自体は実際には' Read'クラスで定義されていないので、オーバーロードすることはできません。 – chepner

答えて

3

readを使用して行う方法を示します。しかし、これは非常に珍しく、lookupを使うことができるので、私はそれを悪い考えだと考えています。ここで

{-# LANGUAGE FlexibleContexts, FlexibleInstances #-} 

type DB = [(String, String)] 

instance Read (DB -> (String, String)) where 
    readsPrec _ = \key -> let 
    f db = case lookup key db of 
     Just x -> ("found", x) 
     Nothing -> ("not found", "data for " ++ key ++ " does not exist") 
    in [(f, "")] 

我々はタイプDB -> (String, String)ためReadのインスタンスを定義します。 read関数のタイプはRead a => String -> aなので、このインスタンスはreadString -> DB -> (String, String)のオーバーロードを与えます。

このインスタンスでは、タイプRead a => Int => ReadS areadsPrecが定義されています。ここで、ReadS aString -> [(a, String)]のエイリアスです。したがって、当社のreadsPrec実装のタイプはInt -> String -> [(DB -> (String, String), String)]である必要があります。 "優先順位"の引数は気にしないので、それを無視します(_)。このインスタンスでは1つの結果しか返さないので、[(f, "")]を返してください。DB -> (String, String)ののkeyを引数のdbで実行するタイプの関数である場合、fが返されます。

今、私たちはそうのように、このインスタンスを使用することができます:

> read "foo" [("foo", "bar")] :: (String, String) 
("found","bar") 

> read "baz" [("foo", "bar")] :: (String, String) 
("not found","data for baz does not exist") 

再び私はこれが実際のコード、あなただけの直接lookupを使うべきで混乱を引き起こす可能性が異例のインスタンスであることを強調します。

4

あなたが望む機能は、プレリュードの一部であるlookupです。

> :t lookup 
lookup :: Eq a => a -> [(a, b)] -> Maybe b 
> let dbList = [("key1", "value1")] 
> lookup "key1" dbList 
Just "value1" 
> lookup "key2" dbList 
Nothing 

実際に表示するタプル形式の出力が必要な場合は、結果をパターンマッチングできます。

case lookup dbList someKey of 
    Just x -> ("found", x) 
    Nothing -> ("not found", "data for " ++ key ++ " does not exist") 
関連する問題