Sal
Sal

Reputation: 4326

Bug in while loop

I can't figure out what the bug is in the toy while loop I wrote below. It works for one input, but hangs for other inputs. Here is the code - the while loop takes a vector, a predicate on vector, and transformation function on vector, and returns another vector:

import Data.Vector.Unboxed as U

while :: Vector Int -> (Vector Int -> Bool) -> (Vector Int -> Vector Int) -> Vector Int
while v p f = go 0 v
      where go n x = if (p x) then go (n+1) (f x)
                              else x

test :: Vector Int -> Vector Int
test a = while a (\x -> (x!0) < 2) (\x -> U.map (+1) a)

main = print $ test (U.fromList [0])

This hangs on execution of main. On the other hand, if I change test to:

test a = while a (\x -> (x!0) < 1) (\x -> U.map (+1) a)

I get a termination with result (ghci output below):

λ: main
fromList [1]

I feel I must be missing something. I looked hard at the function, but can't figure out what I am doing wrong. It looks like predicate can't be executed more than twice.

BTW, it works with other types like Int.

   while :: Int -> (Int -> Bool) -> (Int -> Int) -> Int
    while i p f = go 0 i
          where go n x = if (p x) then go (n+1) (f x)
                                  else x

    test :: Int ->  Int
    test a = while a (\x -> x < 2) (\x -> x+1)

    main = print $ test 0

ghci output:

λ: main
2

GHC version: 7.6.1

Vector version: 0.10.0.1

Upvotes: 2

Views: 141

Answers (1)

sdcvvc
sdcvvc

Reputation: 25644

test a = while a (\x -> (x!0) < 1) (\x -> U.map (+1) a)

should be

test a = while a (\x -> (x!0) < 1) (\x -> U.map (+1) x)

or

test a = while a (\x -> (x!0) < 1) (U.map (+1))

Otherwise the function you are iterating ignores its argument.


Your loop increases a counter, but does not use it. You can remove it:

while v p f = go v
      where go x = if p x then go (f x) else x

Upvotes: 6

Related Questions