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

本秂侑毒 提交于 2021-02-07 14:43:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!