BW12
BW12

Reputation: 11

Haskell : Increment index in a loop

I have a function that calculates f(n) in Haskell. I have to write a loop so that it will start calculating values from f(0) to f(n), and will every time compare the value of f(i) with some fixed value. I am an expert in OOP, hence I am finding it difficult to think in the functional way. For example, I have to write something like

while (number < f(i)) 
   i++

How would I write this in Haskell?

Upvotes: 0

Views: 3816

Answers (4)

Lee
Lee

Reputation: 144176

Instead of explicit recursion, you can use until e.g.

findGreaterThan :: (Int -> Int) -> Int -> Int -> (Int, Int)
findGreaterThan f init max = until (\(v, i) -> v >= max) (\(v, i) -> (f v, i + 1)) (init, 0)

this returns a pair containing the first value to fail the condition and the number of iterations of the given function.

Upvotes: 0

chi
chi

Reputation: 116174

You can generate the list of the is such that f i is larger than your number:

[ i | i<-[0..] , f i > number ]

Then, you can simply take the first one, if that's all you want:

head [ i | i<-[0..] , f i > number ]

Often, many idiomatic loops in imperative programming can be rephrased as list comprehensions, or expressed through map, filter, foldl, foldr. In the general case, when the loop is more complex, you can always exploit recursion instead.

Keep in mind that a "blind" translation from imperative to functional programming will often lead to non-idiomatic, hard-to-read code, as it would be the case when translating in the opposite direction. Still, I find it relieving that such translation is always possible.

If you are new to functional programming, I would advise against learning it by translating what you know about imperative programming. Rather, start from scratch following a good book (LYAH is a popular choice).

Upvotes: 1

Mokosha
Mokosha

Reputation: 2822

The first thing that's weird from a functional approach is that it's unclear what the result of your computation is. Do you care about the final result of f (i)? Perhaps you care about i itself. Without side effects everything neends to have a value.

Let's assume you want the final value of the function f (i) as soon as some comparison fails. You can simulate your own while loops using recursion and guards!

while :: Int -> Int -> (Int -> Int) -> Int
while start number f
  | val >= number = val
  | otherwise = while (start + 1) number f
    where
      val = f start

Upvotes: 0

MathematicalOrchid
MathematicalOrchid

Reputation: 62848

The standard approach here is

  1. Create an infinite list containing all values of f(n).
  2. Search this list until you find what you're after.

For example,

takeWhile (number <) $ map f [0..]

If you want to give up after you reach "n", you can easily add that as a separate step:

takeWhile (number <) $ take n $ map f [0..]

or, alternatively,

takeWhile (number <) $ map f [0 .. n]

You can do all sorts of other filtering, grouping and processing in this way. But it requires a mental shift. It's a bit like the difference between writing a for-loop to search a table, versus writing an SQL query. Think about Haskell as a bit like SQL, and you'll usually see how to structure your code.

Upvotes: 1

Related Questions