Haskell列表理解

use*_*202 2 haskell list-comprehension list

我正试图做一个haskell问题,因为我正在努力学习Haskell.

这个问题给了我以下类型定义:
type Word = String
type Line = [Word]
type Book = [Line]

然后问题要求我定义一个函数索引:: Word - > Book - > [Int],它接受一个单词和一本书,并返回单词出现的行号.例如:
index "example" [["example", "town"], ["example", "cat", "this"]] = [1,2]

到目前为止,我已经使用了zip book [1 ..长度书]将行号附加到每一行,这样就可以给我了

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

那我怎么才提取行号呢?我假设我会使用列表推导,但我不知道该怎么做.

Wil*_*ess 5

这些事情的一般列表理解方案是

g xs = [i | (x,i) <- zip xs [1..], pred x]
Run Code Online (Sandbox Code Playgroud)

pred是一个作用于xs输入列表元素的谓词; 仅对于那些通过测试的人,他们的原始索引包含在输出中.当然,这可以通过更高阶函数来完成,如

g xs = map snd . filter (pred . fst) . (`zip` [1..]) $ xs
Run Code Online (Sandbox Code Playgroud)

(.)是函数组合运算符:pred . fst == (\p -> pred (fst p)).因此,也可以写上述行

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

对你来说更可读的东西.

更新: filter也可以实现为

filter pred = concatMap (\x -> [x | pred x])
Run Code Online (Sandbox Code Playgroud)

所以映射可以融合在一起,给我们

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

concatMap也可以替换foldMap,join . map ...甚至asum . map ....

  • @kaan:如果你打开优化,他们都会编译成相同的代码,所以挑选适合你的东西. (3认同)