NegativeFlow
NegativeFlow

Reputation: 13

Haskell Recursion - How to call another function with original values but only once

I am trying to figure out how I can recursively define a function while also calling a second function at one of the original integer max values. I don't want to add another integer input however I want to call the second function with the integer from the first function (but only once) I would happily also shorten this down into 1 function if that's better/possible

testFunction::Int->String
testFunction s 
 |s == 0 = ""
 |otherwise = "abc" ++ testFunction (s-1) ++ testFunction2 s

testFunction2::Int->String
testFunction2 s
 |s == 0 = "" 
 |otherwise = testFunction2 (s-1)++"cba"

For example, this will call testFunction recursively and then because it does this it will call testFunction2 multiple times with s-1 in the main function. I only want the content of testFunction2 to be called once and only with the initial value of S without adding any other int inputs. Say I called 'testFunction 2' it currently outputs 'abcabccbacbacba', however I only want cba outputted twice so I really want 'abcabccbacba' Thank you for the help :)

Upvotes: 1

Views: 350

Answers (2)

Will Ness
Will Ness

Reputation: 71109

Your function looks like an equivalent of

testFunction s = concat (replicate s "abc") ++
                 concat (replicate (s*(s+1)`div`2) "cba")

and you apparently want

testFunction s = concat (replicate s "abc") ++ 
                 concat (replicate s "cba")

So, there it is, shortened down into one function. But it's not recursive (it's not clear to me if that's a hard requirement here, or not).

It could also be written

 = concat (replicate s "abc"  ++  replicate s "cba")
 = concat $ concatMap (replicate s) ["abc", "cba"]
 = ["abc", "cba"] >>= replicate s >>= id

Upvotes: 1

K. A. Buhr
K. A. Buhr

Reputation: 51029

The usual way of doing this sort of thing is to break the function up into some non-recursive "top-level" processing and a recursive helper, usually defined in a where clause and given a generic name like go or step or loop.

So, you might write:

testFunction :: Int -> String
testFunction s
  | s == 0 = ""
  | otherwise
    -- here's the top-level processing
    = "abc" ++ go (s-1) ++ testFunction2 s
  where
    -- here's the recursive helper
    go s | s == 0 = ""
         | otherwise = "abc" ++ go (s-1)

In this example, this results in some repeated code. You can refactor to remove some of the duplication, though it may be difficult to remove all of it (e.g., the s == 0 handling):

testFunction :: Int -> String
testFunction s
  | s == 0 = ""
  | otherwise = go s ++ testFunction2 s
  where
    go s | s == 0 = ""
         | otherwise = "abc" ++ go (s-1)

Upvotes: 2

Related Questions