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?
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.
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.
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.
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.
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()
Haskell does not have an intrinsic equivalent of while
loops based on mutable state.
Instead, you typically
map
family of functions over a range of values to produce a new range of valuesfilter
family of functions over a range of values to produce a new subset of that range, with certain conditions fulfilledfold
family of functions to aggregate something over that range.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With