0

I'm writing a function like this:

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ]
      let t1 = [ w | (u,v) <- zip t (tail t), let w = if (u == 2) && (v == 0) then 2 else v]
      head t : t1

What the first let does is: return a list like this: [2,0,0,0,1,0], from the second let and the following line, I want the output to be like this: [2,2,2,2,1,0]. But, it's not working and giving parse error!!

What am I doing wrong?

2 Answers 2

3

There are two kinds of lets: the "let/in" kind, which can appear anywhere an expression can, and the "let with no in" kind, which must appear in a comprehension or do block. Since your function definition isn't in either, its let's must use an in, for example:

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ] in
      let t1 = [ w | (u,v) <- zip t (tail t), let w = if (x == 2) && (y == 0) then 2 else y] in
      return (head t : t1)

Alternately, since you can define multiple things in each let, you could consider:

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ]
          t1 = [ w | (u,v) <- zip t (tail t), let w = if (x == 2) && (y == 0) then 2 else y]
      in return (head t : t1)

The code has other problems, but this should get you to the point where it parses, at least.

Sign up to request clarification or add additional context in comments.

3 Comments

OK, I tried the first option and it parses. But, I'm getting the result [2,2,0,0,1,0], but I want [2,2,2,2,1,0] as the result from the above example. Why is that happening?
Note that you can insert a do at the beginning to avoid the use of in, even if the final result does not implement Monad
@EricaMaine I have no idea; I really don't understand what you're trying to do. Anyway you should open another question explaining what it is you want to compute, where you think this function is going wrong, and what you've done to try to fix it.
0

With an expression formed by a let-binding, you generally need

let bindings 
in 
  expressions

(there are exceptions when monads are involved).

So, your code can be rewritten as follows (with simplification of r and w, which were not really necessary):

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ if y == 0 && x == 2 then 2 else y | (x,y) <- zip lst1 lst2]
          t1 = [ if (v == 0) && (u == 2) then 2 else v | (u,v) <- zip t (tail t)]
      in
        head t : t1

(Note, I also switched u and v so that t1 and t has similar forms.

Now given a list like [2,0,0,0,1,0], it appears that your code is trying to replace 0 with 2 if the previous element is 2 (from the pattern of your code), so that eventually, the desired output is [2,2,2,2,1,0].

To achieve this, it is not enough to use two list comprehensions or any fixed number of comprehensions. You need to somehow apply this process recursively (again and again). So instead of only doing 2 steps, we can write out one step, (and apply it repeatedly). Taking your t1 = ... line, the one step function can be:

testing' lst = 
    let               
        t1 = [ if (u == 2) && (v == 0) then 2 else v | (u,v) <- zip lst (tail lst)]
    in
      head lst : t1

Now this gives:

*Main> testing'  [2,0,0,0,1,0]
[2,2,0,0,1,0]

, as expected.

The rest of the job is to apply testing' as many times as necessary. Here applying it (length lst) times should suffice. So, we can first write a helper function to apply another function n times on a parameter, as follows:

apply_n 0 f x = x
apply_n n f x = f $ apply_n (n - 1) f x

This gives you what you expected:

*Main> apply_n (length [2,0,0,0,1,0]) testing' [2,0,0,0,1,0]
[2,2,2,2,1,0]

Of course, you can wrap the above in one function like:

testing'' lst = apply_n (length lst) testing' lst

and in the end:

*Main> testing''  [2,0,0,0,1,0]
[2,2,2,2,1,0]

NOTE: this is not the only way to do the filling, see the fill2 function in my answer to another question for an example of achieving the same thing using a finite state machine.

1 Comment

I did what you told but, I'm getting a different error now, a type error. I edited the question to write that. Could you tell me what I'm doing wrong there?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.