我对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重现类似的东西吗?
答案 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使用多种不同方式的组合来“遍历”数据(列表等)。
帮助这一点的两件重要事情是:
例如,我在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
。