如何在Haskell中编写for循环?

时间:2019-09-09 01:41:12

标签: list haskell functional-programming

我对Haskell真的很陌生,也对如何实现for循环感到困惑,因为我知道我们需要为它们使用递归。

例如,我有一个列表[1,2,2,4,1],并且想要编写一个函数来将每个2更改为3。我将如何去做呢?在Java中,我知道我会写以下内容

public void replace_two(List<Integer> ints) {
        int i = 0;
        for (int x: ints) {
            if (x == 2) {
                ints.set(i, 3);
            }
            i++;
        }
        System.out.println(ints);
    }

但是我不确定如何用Haskell重现类似的东西吗?

5 个答案:

答案 0 :(得分:11)

Haskell中没有for循环的唯一替代品。替换取决于您要执行的操作。在这种情况下,使用map是合适的:

replace_two = map go
  where
    go 2 = 3
    go x = x

它的工作原理如下:

Prelude> replace_two [1,2,2,4,1]
[1,3,3,4,1]
Prelude>

答案 1 :(得分:3)

Haskell使用多种不同方式的组合来“遍历”数据(列表等)。

帮助这一点的两件重要事情是:

  1. 易于声明函数并将其传递给我们,类似于我们对oops语言中的变量所做的操作
  2. 广泛的模式匹配

例如,我在haskell中声明一个函数,如果输入为3,则返回2,否则返回输入。

return2 x = if x == 3 then 2 else x

现在,我们想将此功能应用于列表的每个元素。所以我们将使用模式匹配

apply (x:xs) = return2 x : apply xs
apply [] = []

这里,模式x:xs将中断列表,并占据x中的第一个元素,而xs将具有列表的其余部分。在该函数内部,您可以看到我们已递归应用它。

我尚未在IDE中检查以上代码,因此可能存在语法错误,还有其他您需要验证的内容(列表结尾,在上述代码中,该函数会导致异常)。

上面的模式很常见,因此核心库中还有另一个函数可以做到这一点,称为map。因此,您可以这样做:

map return2 [your list]

正如我在haskell中所说的那样,有很多方法可以使事物本质上循环,但是从根本上讲,它们分解为将功能应用于数据结构中的各个项目。在其之上构建了许多haskell函数,例如地图,折叠等。

我建议您使用几种在线资源之一来更熟悉Haskell构造。我喜欢并易于遵循的是Learn you a hakell

答案 2 :(得分:1)

另一种使用模式和递归的基本方法。

replace :: [Int] -> [Int]
replace [] = [] -- base case
replace (2:x)  = 3:replace(x) --if 2 then replace by 3
replace (y:x) = y:replace(x) -- do nothing

答案 3 :(得分:0)

使用map和匿名功能:

λ> map (\x -> if x==2 then 3 else x) [1,2,2,4,1]
[1,3,3,4,1]

答案 4 :(得分:-1)

除了map,也许您可​​以使用forM中的Control.Monad来模仿其他命令式语言中的for循环:

import Control.Monad
arr = [1, 2, 2, 4, 1]
forM arr $ \i ->
    if i == 2 then return 3 else return i

但是,您需要了解什么是Monad