rel1x
rel1x

Reputation: 2441

Mistake in iterate, Haskell

My program, where n = 4:

f n = take n (iterate (1+) 1)

main = do
    n <- getLine
    print(f (product(map read $ words n :: [Int])))

if f n = take n (iterate (1+) 1) my answer is [1,2,3,4]. If each element in list divides on 4 answer is [4, 2, 1.3333333333, 1].

I modify code f n = take n (iterate (\x->(4/(x+1))) 1) but now my answer is wrong: it's [1.0,2.0,1.3333333333333333,1.7142857142857144], not [4, 2, 1.3333333333, 1].

Where is my mistake?

Upvotes: 0

Views: 85

Answers (2)

Jonathan Cast
Jonathan Cast

Reputation: 4635

Try writing it in C:

f n = take n $ iterate (1+) 1

translates to

void
f(int n) {
    int i;
    double t = 1;

    for (i = 0; i < n; i++) {
        printf("%g\n", t);
        t = 1 + t;
    }
}

So

f n = take n (iterate (\x->(4/(x+1))) 1)

translates to

void
f(int n) {
    int i;
    double t = 1;

    for (i = 0; i < n; i++) {
        printf("%g\n", t);
        t = 4 / (t + 1);
    }
}

which has the same effect. You're doing the division (4 /) in between the (1 +) additions, which is why you're getting the wrong answer. In C, you put 4 / t in the output and 1 + t when updating the temporary:

void
f(int n) {
    int i;
    double t = 1;

    for (i = 0; i < n; i++) {
        printf("%g\n", t / 4);
        t = t + 1;
    }
}

and the Haskell equivalent of that is using two list functions:

f n = take n $ map (4/) $ iterate (1+) 1

Upvotes: 0

karakfa
karakfa

Reputation: 67497

Define f as

   f :: Int -> Double
   f n = sum $ map (4/) $ map fromIntegral [1..n]

you have to watch for mixing numerical types in computations. Now your function should work

> f $ product (map read $ words "23 4 32" :: [Int])
34.259639888367765

Upvotes: 2

Related Questions