迭代haskell中的列表

时间:2012-01-26 06:25:39

标签: haskell

我有一个字符列表::[[Char]]列表。 我需要遍历字符串列表以及每个字符串中的每个字符。

说,我的列表出现在这个变量中。

let xs

请建议一种简单的迭代方式。

4 个答案:

答案 0 :(得分:15)

如果要将函数f应用于列表的每个元素,请执行以下操作:

[a, b, c, d] → [f a, f b, f c, f d]

然后map f xs就可以了。 map将元素上的函数转换为列表上的函数。因此,我们可以将其嵌套以对列表列表进行操作:如果fa转换为b s,map (map f)[[a]]转换为[[b]] }}第

如果您想要为列表的每个元素执行一些IO操作(这更像传统迭代),那么您可能正在寻找forM_ 1

forM_ :: [a] -> (a -> IO b) -> IO ()

你给它一个函数,它按顺序用列表的每个元素调用它。例如,forM_ xs putStrLn是一个IO操作,它将在xs中打印出自己行中的每个字符串。以下是forM_

更多参与使用的示例
main = do
  ...
  forM_ xs $ \s -> do
    putStrLn "Here's a string:"
    forM_ s print
    putStrLn "Now it's done."

如果xs包含["hello", "world"],则会打印出来:

Here's a string:
'h'
'e'
'l'
'l'
'o'
Now it's done.
Here's a string:
'w'
'o'
'r'
'l'
'd'
Now it's done.

1 forM_实际上有一个更通用的类型,但我所展示的更简单的版本在这里更相关。

答案 1 :(得分:3)

map (map f) l

其中f :: Char -> Foo是适用于每个Charl :: [[Char]]的函数 返回l' :: [[Foo]]

答案 2 :(得分:3)

迭代的“正确”方式实际上是 fold 。您可能想要对列表执行的任何操作都可以通过折叠完成。让我们考虑一下你想做什么。你可能会想到这样的事情:

for (row in xs):
  for (c in row):
    doSomething

问题是,你可能在doSomething中使用了可变变量。没关系,我们可以解决这个问题。所以假设你有这个。

def iter2d(xs):
  outerVar = outerInit
  for (row in xs):
    innerVar = innerInit(row)
    outerVar.adjust1(row)
    for (c in row):
      innerVar.adjust2(c)
      outerVar.adjust3(c, innerVar)
  return outerVar

让我们把它翻译成折叠。和不变性。

iter2d :: [[Char]] -> Something
iter2d xs = foldl' outerStep outerInit xs
  where outerInit = ... -- same as outerInit above
        outerStep acc row = fst $ foldl' innerStep innerInit' row)
          where innerInit' = ((adjust1 acc row), innerInit row)
        innerInit row = ... -- same as innerInit above
        innerStep (outAcc, inAcc) c = (outAcc', inAcc')
          where inAcc' = adjust2 inAcc c
                outAcc' = adjust3 outAcc c inAcc'

注意到具有不变性,我们不得不指出outAc'取决于inAcc',而不是inAcc,这意味着innerVar 之后的“状态” 它已更新。

现在你可能会说“哇,Haskell看起来很难看,为什么我会想要使用Haskell”。是的,它确实看起来很难看,但仅仅因为我将它定制为命令式代码的直接翻译。一旦你习惯使用 folds 而不是“遍历列表”,那么你会发现折叠是一种非常强大的技术,它可以让你以比循环更优雅的方式做很多事情。允许。

答案 3 :(得分:3)

就是这样:

[c | x <- xs, c <- x]