Dimitar
Dimitar

Reputation: 4791

Stopping condition on a recursive function - Haskell

So, I have this function which aims to align the text on the left without cutting words(only white spaces). However my problem is that I cannot find a stopping condition of the function and it goes infinitely.

f n "" = ""          --weak condition
f n s  = if n >= ((maximum . map length . words) s) then if (s !! n == ' ' || s !! n == '\t' || s !! n == '\n') 
                                                    then take n s ++ "\n" ++ (f n ( drop n s)) else f (n-1) s 
                                                    else error "Try bigger width!"

Well, basically if the n is smaller than the longest word then it prompts error, else it ''cuts'' the string in the white spaces until it reaches a not white space character, then it calls itself recursively for n-1. I use also putStr to avoid "\n" in the output.

However, as I already said the stopping condition is too weak or non-existent. If there are other flows in the code or possible optimizations(e.g. less ifs), please tell.

Upvotes: 0

Views: 823

Answers (1)

user3426575
user3426575

Reputation: 1773

Your code doesn't handle the case where a line is shorter than the maximum length.

This is somewhat obscured by another bug: n is decremented until a whitespace is found, and then f is called recursively passing this decremented value of n, effectively limiting all subsequent lines to the length of the current line.

(Also, you might want to drop n + 1 characters from s so the original whitespace isn't included in the output.)

You can avoid ifs by using patterns:

f n "" = "" -- weak condition
f n s
  | n >= (maximum . map length . words) s =
      if s !! n == ' ' || s !! n == '\t' || s !! n == '\n'
      then take n s ++ "\n" ++ f n (drop n s)
      else f (n - 1) s
  | otherwise = error "Try bigger width!"

Upvotes: 3

Related Questions