Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the equivalent statement of a while loop in Haskell?

Being very new to Haskell, I'm wondering how to 1) compute something until a certain criterion is satisfied, and then 2) return the computed value.

In the languages I know, you would use a while loop for that. How do you do it in Haskell?

like image 278
Myke Avatar asked Dec 10 '14 14:12

Myke


People also ask

What is the statement of while loop?

The WHILE LOOP statement runs one or more statements while a condition is TRUE . The WHILE LOOP statement ends when the condition becomes FALSE or NULL , or when a statement inside the loop transfers control outside the loop or raises an exception.

What is another name of while loop statement?

Because the while loop checks the condition/expression before the block is executed, the control structure is often also known as a pre-test loop.

How do you use loops in Haskell?

Someone told me that when you want to do loops in Haskell think of either recursion or list comprehensions. Not relevant to your question here, but suppose you want to add all the elements in a list. Of course you need to iterate over all the elements. Recursion will work, and so will using a list comprehension.


3 Answers

You should use recursion:

func :: <function type>
func <arguments> = 
    if condition 
        then <recursive call>
        else computedValue

There are also other utilities you'll discover in the future, such as until, that will help you with this. In the end it really depends on the semantic of the loop and condition. For example if the condition is simply "until we reach the end of a list" you can simply use map or one of the fold-family functions.

like image 164
Shoe Avatar answered Sep 28 '22 20:09

Shoe


The answer is recursion. To give a pedantic example:

In Python:

def fib(n):
    a = 0
    b = 1
    while n > 0:
        a, b = b, a + b
        n -= 1
    return b

In Haskell:

fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

Or equivalently without pattern matching

fib n = if n == 0 || n == 1 then 1 else fib (n - 1) + fib (n - 2)

Or more efficiently

-- the local variable fibs is an infinite list of all Fibonacci numbers
fib n = fibs !! n where fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

If you want to do something like read text from STDIN until you get a line that reads q, then the easiest way is something like

import Control.Monad (unless)

prompt :: IO ()
prompt = do
    -- get input from user
    l <- getLine
    -- unless will execute its block if the condition is False
    unless (l == "q") $ do
        -- echo back to the user
        putStrLn $ "You entered: " ++ l
        prompt  -- recursive step here

Or in Python

def prompt():
    l = input()
    while l != "q":
        # Assuming Python 3
        print("You entered: " + l)
        l = input()
like image 32
bheklilr Avatar answered Sep 28 '22 20:09

bheklilr


Haskell does not have an intrinsic equivalent of while loops based on mutable state.

Instead, you typically

  • use map family of functions over a range of values to produce a new range of values
  • use filter family of functions over a range of values to produce a new subset of that range, with certain conditions fulfilled
  • use fold family of functions to aggregate something over that range
  • use recursion to do whatever you want (except mutating input, of course).

.

Of course, Haskell and libraries provide functions to make your life easier, but while while loops can be considered idiomatic/"first class" in imperative languages, what is idiomatic/"first class" in Haskell (and other functional programming languages) is recursion, mapping, filtering and folding.

like image 32
Sebastian Mach Avatar answered Sep 28 '22 21:09

Sebastian Mach