-2

I am relatively new to Haskell. I understand the concepts of recursion and such. But, I am having trouble thinking through how to convert something like the following functional pseudocode into 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`
}

(note A, B, C and D are constants)

5
  • I understand how to write a function and recursively call it to the base case, so I could iterate through a list of number and do something with each one. I'm having trouble figuring out how to carry values of variables x and y through the recursion because to compute x and y in the base case (count = 100) requires the values of x and y from the previous iterations of the loop. Commented Dec 16, 2015 at 21:58
  • 4
    Instead of updating variables, think of the loop body as a function that takes two variables (x, y) and returns two variables (x', y'). Your loop is then that function applied to its own output 100 times. Commented Dec 16, 2015 at 21:58
  • Possible duplicate of How to use recursion nested for loop in haskell without forloop Commented Dec 16, 2015 at 22:20
  • @jberryman I don't think it is an exact duplicate because the code in the OP contains some printing inside the loop body, if you want to translate this faithfully you must preserve that as well. Commented Dec 16, 2015 at 23:36
  • Why is this downvoted? :\ Commented Dec 17, 2015 at 5:59

2 Answers 2

5

As suggested, the functional way of doing this is to turn your loop body into a function takes and returns the variables you're interested in:

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

You can then apply the function to itself 100 times with (0,0) as your start values:

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

And then, optionally, dump all the intermediate values unceremoniously to the screen:

main = print values
Sign up to request clarification or add additional context in comments.

Comments

3

You can very easily define a function to help you write things that look like imperative loops:

import Control.Monad 

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

The definition is not really important (many, many ways to write this function), rather, to understand what it does, look at the type. Given some list of i - the range of values to loop over, and some initial value for your loop, an a, and finally, a function which given a value (i) and a loop state (a), returns a new loop state in some context m. This function produces a computation in that context m which yields the last state.

Use it simply like so:

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) 

and

> runghc test.hs 12 34 56 78

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.