2015-12-16 135 views
-4

我對Haskell比較新。我理解遞歸等概念。但是,我無法通過如何類似下面的功能的僞代碼轉換爲Haskell的思考:Convert For Loop to Haskell

x = 0 
y = 0 
For Count = 1 To 100 { 
    Print (Count, x, y) 
    z = -(A*x + B*y)/C - D 
    x = x + y 
    y = y + z` 
} 

(注意A,B,C,d爲常數)

+0

我知道如何編寫一個函數,遞歸調用它的基本情況,所以我可以迭代一個數字列表並對每個數字進行一些操作。我很難找出如何通過遞歸來攜帶變量x和y的值,因爲在基本情況下計算x和y(count = 100)需要來自以前循環迭代的x和y的值。 – JeffC

+3

不是更新變量,而是將循環體看作一個函數,它接受兩個變量'(x,y)'並返回兩個變量'(x',y')'。然後你的循環被應用於自己的輸出100次。 –

+0

可能的重複[如何使用遞歸嵌套for循環haskell沒有forloop](http://stackoverflow.com/questions/26203493/how-to-use-recursion-nested-for-loop-in-haskell-without- forloop) – jberryman

回答

3

你可以很容易地定義一個函數幫你寫的東西看起來像命令式的循環:

import Control.Monad 

loop :: Monad m => [i] -> a -> (i -> a -> m a) -> m a 
loop is a0 f = foldr (>=>) return (map f is) a0 

的定義並不重要(很多很多的方式來寫這個功能),而是要了解它做什麼,看的類型。給定一些列表i - 要循環的值的範圍,以及您的循環的一些初始值,a,最後,一個給定值(i)和循環狀態(a)的函數返回一個新的循環狀態在某些情況下m。這個函數在上下文中產生一個計算結果m,它產生最後一個狀態。

使用它只是像這樣:

import System.Environment 
main = do 
    (c0:c1:c2:c3:_) <- map read <$> getArgs 
    loop [1..100] (0,0) $ \count (x,y) -> do 
    print (count,x,y) 
    let z = -(c0*x + c1*y)/c2 - c3 
    return (x+y,y+z) 

> runghc test.hs 12 34 56 78 
4

如所建議的,這樣的功能的方法是把你的循環體成函數將返回的變量,你」重新關注:

f (x, y) = 
    let 
     z = -(a*x + b*y)/c - d 
     x' = x + y 
     y' = y + z 
    in 
     (x', y') 

然後,您可以將函數應用到自身100次(0,0)作爲起始值:

values = take 100 $ iterate f (0,0) 

然後,可選,傾倒所有的中間值,毫不客氣地在屏幕上:

main = print values