2

私は Haskell を学ぼうとしているので、haskell の質問をしようとしています。

質問により、次の型定義が得られます。
type Word = String
type Line = [Word]
type Book = [Line]

次に、質問では、関数 index :: Word -> Book -> [Int] を定義するように求められます。これは、単語と本を取り、単語が表示される行番号を返します。例えば:
index "example" [["example", "town"], ["example", "cat", "this"]] = [1,2]

これまでのところ、zip book [1 .. length book] を使用して各行に行番号を付けました。

[(["example","town"],1),(["example","cat","this"],2)]

次に、行番号のみを抽出するにはどうすればよいですか? リスト内包表記を使用すると仮定していますが、その方法がわかりません。

4

3 に答える 3

6

これらの一般的なリスト内包表記スキームは次のとおりです。

g xs = [i | (x,i) <- zip xs [1..], pred x]

predxs入力リスト の要素に作用する述語です。テストに合格したものについてのみ、元のインデックスが出力に含まれます。もちろん、これは高階関数で行うことができます。

g xs = map snd . filter (pred . fst) . (`zip` [1..]) $ xs

(.)は関数合成演算子です: pred . fst == (\p -> pred (fst p)). したがって、上記の行も書くことができます

g xs = map snd . filter (\(x,i) -> pred x) . (`zip` [1..]) $ xs

あなたにとってより読みやすいものは何でも。

更新: filterとしても実装可能です

filter pred = concatMap (\x -> [x | pred x])

マッピングを融合できるので、

g :: (a -> Bool) -> [a] -> [Int]
g pred = concatMap (\(x,i) -> [i | pred x]) . (`zip` [1..])

concatMapfoldMapjoin . map ...さらには に置き換えることもできますasum . map ...

于 2013-08-08T15:41:17.700 に答える
2

他の投稿で述べたように、zip関数を使用して各行を行番号で装飾できます。次に、リスト内包表記を使用して検索できます。

search :: Word -> Book -> [Int]  
search w b =  
  [n | (line, n) <- lines, elem w line]  
  where lines = zip b [1..]

次を使用して関数を定義することもできますfoldl(スタイルが良いかどうかはわかりませんが、私はまだ Haskell の初心者です)。

search :: Word -> Book -> [Int]
search w b =
  fst $ foldl foo ([], 1) b
  where foo (rs, n) line | elem w line = (n : rs, n+1)
                         | otherwise = (rs, n+1)

これを再帰的に定義することもできます。

于 2013-08-08T18:33:39.503 に答える
2

mapリスト内のすべての要素に関数を適用する を使用できます。適用する関数はsnd、2 番目の要素を抽出する です。

λ> let xs = [(["example","town"],1),(["example","cat","this"],2)]
λ> map snd xs
[1,2]

残りのコードを見せてください。あなたが使用したと述べましたTzip book [1 .. length book]-通常、関数を使用するよりも簡単で効率的な方法がありlengthます。より「Haskelish」な方法を提案できるかもしれません。

編集:フィルタリング

関心のある単語を含むすべてのエントリを検索する単純な関数を作成することで、リストをフィルタリングできます。以下の例では、containsWordこの目的のために次のように定義しています。

λ> let xs = [(["example","town"],1),(["example","cat","this"],2)]
λ> let containsWord w (ws,_) = w `elem` ws
λ> let ys = filter (containsWord "cat") xs
λ> map snd ys
[2]

または、関数をインラインで定義する場合:

λ> let xs = [(["example","town"],1),(["example","cat","this"],2)]
λ> let ys = filter (\(zs,_) -> "cat" `elem` zs) xs
λ> map snd ys
[2]

もちろん、これらすべてにリスト内包表記を使用できます。しかし、 や のような関数を使用するmapfilter、より読みやすいコードになる場合があります。今から数か月後にコードを振り返るmapfilter、 と の目的がすぐに理解できますが、リスト内包表記が実際に何をしているのかを理解するには、より詳細な調査が必要です。リスト内包表記は、使い慣れた関数でまだカバーされていない状況にのみ使用することを好みます。

于 2013-08-08T15:06:54.840 に答える