问题
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?
回答1:
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.
回答2:
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.
回答3:
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()
来源:https://stackoverflow.com/questions/27404063/what-is-the-equivalent-statement-of-a-while-loop-in-haskell