0

私は持っている:

type Person     = String
type Book       = String
type Database   = [(Person,[Book])]

関数を定義しようとしています:

books :: Database -> Person -> [Book]

1) タプルのリスト (文字列と文字列のリストを含む) 2) 文字列名

文字列のリスト(つまり、データベースからの本)を返します

リスト内包表記を使いたいのですが、データベース リスト内のタプルにあるリスト内の要素にアクセスする方法がわかりません。

考え?

データベースの例は次のようになります。

db = [("Bob", ["Red Riding Hood", "Alice in Wonderland"]), ("Carol", ["Game of Thrones"])]

「キャロル」と言うと、[「ゲーム・オブ・スローンズ」] が返されます。

4

3 に答える 3

3

アソシエーションリストがあるので、この機能を使用できますlookup。それはあなたが望むようにほとんど正確に機能します:

getVal :: Database -> String -> Maybe [String]
getVal  = lookup

唯一の違いはMaybe、正しい動作であるIMHOが返されることです。データベースに値がない場合は、調べたときにどうなるか考えてみてください。

ここでパターンマッチングを使用したいので、lookup

lookup                  :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup _key []          =  Nothing
lookup  key ((x,y):xys)
    | key == x          =  Just y
    | otherwise         =  lookup key xys

またはあなたの場合

getVal :: Database -> String -> [String] --Avoids a Maybe if you want
getVal _key []          =  []
getVal  key ((x,y):xys)
    | key == x          =  y
    | otherwise         =  getVal key xys
于 2013-02-03T22:48:19.567 に答える
2

他のポスターlookupが言ったように、ここに行く方法です。連想リストで何かを検索するのは標準的な手順です。

とはいえ、リスト内包表記を使用したソリューションは次のようになります

books :: Database -> Person -> [Book]
books db authorName = [book | (author, bookName) <- db,
                              author == authorName
                              book <- bookName]

(author, bookName)作成者が一致しないタプルを破棄して、タプルを 1 つずつ取り出します。If then は、その著者の書籍を結果に追加します。

繰り返しますが、これは既に標準ライブラリにある関数の一種の回避策を実装しており、一般的に読みにくいものです。本当に、使用しますlookup

于 2013-02-03T23:36:08.427 に答える
1

私はその関数を実装するためにリスト内包表記を使用しません - リスト内包表記はリストを構築するのにより適しています。

あなたが探しているのは Prelude 関数のlookupです:

lookup :: Eq a => a -> [(a, b)] -> Maybe b

ご覧のとおり、引数を交換した場合a ~ Personと交換した後では、ほぼ正しい型になっています。元に戻しb ~ [Book]たいので、すべてをfromMaybe内にラップすると、次のようになります。[Book]Maybe [Book]

books db = fromMaybe [] . flip lookup db
于 2013-02-03T22:55:38.280 に答える