简体   繁体   中英

How to write a for loop in Haskell?

I am really new to Haskell and also really confused about how to implement for loops since I know we need to use recursion for them.

For example, I have a list [1,2,2,4,1] and want to write a function to change every 2 to a 3 . How would I go about doing this? In Java, I know I would write the following

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);
    }

but I am not sure how I could reproduce something else like this with Haskell?

There's not a single replacement for a for loop in Haskell. The replacement depends on exactly what you want to do. In this case, a map would be appropriate:

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

And it works like this:

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

Haskell uses a combination of different ways to 'sort of' loop over data (list, etc.).

The two important things helping this is:

  1. Ease of declaring a function and passing it around similar to what we do to a variable in oops languages'
  2. Extensive pattern matching

So for example I declare a function in haskell to return 2 if input is 3 else return input.

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

Now we want to apply this function to every element of the list. So we will use pattern matching

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

Here the pattern x:xs will break the list and take the first element in x while xs will have the remainder of the list. Inside the function you can see we have applied it recursively.

I have not checked the above code in IDE so might have syntax errors, also there are other things you will want to validate (end of list, in above code the function would cause exception).

The above pattern is quite common, so there is another function in the core libraries that can do this, and is called map. So you could have done:

map return2 [your list]

As I said in haskell there are many ways to essentially loop over things, but at the base they break down to applying the function to individual items in the data structure. There are many haskell functions built on top of it like map, fold, etc.

I would suggest you use one of the several resources online to get more familiar with Haskell constructs. One that I liked and easy to follow is Learn you a hakell

Another basic approach using patterns and recursion.

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

Using map with an anonymous function:

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

Except map , maybe you can use forM from Control.Monad to mimic the for loop in other imperative languages:

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

However, you need to understand what is Monad .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM