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
なので、このインスタンスはread
String -> DB -> (String, String)
のオーバーロードを与えます。
このインスタンスでは、タイプRead a => Int => ReadS a
のreadsPrec
が定義されています。ここで、ReadS a
はString -> [(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
を使うべきで混乱を引き起こす可能性が異例のインスタンスであることを強調します。
'read :: Read a => String - > a'は、文字列表現から特定の型の値を作成するためのものであり、データベースの参照を行うものではありません。 – chepner
ご意見ありがとうございます。私の上司は私に** read **関数を使用してコード例を期待していましたが、解決できる方法が見つからないため、これが可能かどうか確かめたいと思っていました。 –
彼は 'Read'クラスを知っていますか? 'read'クラス自体は実際には' Read'クラスで定義されていないので、オーバーロードすることはできません。 – chepner