How to check if you are in the first iteration of a loop in Haskell?

Viewed 228

I could understand if the question doesn't really clarify my problem, so here is some more explanation:

I am trying to add the string "+" at the start of my string, which I get like this:

printLine :: [Int] -> String  --Type of the function
printLine [] = ""             --Base case

printLine (x:xs) = "+" ++ foldr (++) "+" f ++ printLine xs
                 where f = replicate x "-"

The result I get from the above:

+-----++------++------++------+

The result I would like to get:

+-----+------+------+------+

Basically my question is: How do I add "+" only at the start? I can understand that this might be a silly question, but I am stuck for a while now and I can't find the answer on SO or elsewhere.

2 Answers

Proposal: don't detect when you're in the first iteration, which is hard; instead detect when you're in the last iteration, which is easy because it's the [] case in the first line.

printLine :: [Int] -> String
-- final iteration; add an extra + at the end
printLine [] = "+"

-- not the final iteration; don't include a + at the end of the -s
printLine (x:xs) = "+" ++ replicate x '-' ++ printLine xs

If an empty list must map to an empty string, one option is to fold with a special case for an empty list.

printLine :: [Int] -> String
printLine [] = ""
printLine xs = foldr (\x res -> '+' : replicate x '-' ++ res) "+" xs

So that

λ> map printLine [[], [1..4], [5]]
["","+-+--+---+----+","+-----+"]

Alternatively, since the original question asked for control during the first iteration, one option is to use a helper function. Here are two alternatives.

printLine' :: [Int] -> String
printLine' [] = ""
printLine' xs = '+' : go xs
  where go :: [Int] -> String
        go [] = ""
        go (n:ns) = replicate n '-' ++ "+" ++ go ns

printLine'' :: [Int] -> String
printLine'' xs = go True xs
  where go :: Bool -> [Int] -> String
        go _ [] = ""
        go isFirst (n:ns) = (if isFirst then "+" else "")
          ++ replicate n '-' ++ "+" ++ go False ns

With these definitions

λ> map printLine' [[], [1..4], [5]]
["","+-+--+---+----+","+-----+"]
λ> map printLine'' [[], [1..4], [5]]
["","+-+--+---+----+","+-----+"]
Related