Reputation: 4326
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
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