1

Im currently learning Haskell for University and doing old Assignments. Regarding a Task I have a question. Im supposed to write a Function that Takes an Int a Char and a List and puts the Char at the beginning and at an intervall given by the number into the List, should the List be divisable by the given Int the Char should also be put at the end od the list.

like this

> example_wrap_1 = wrap 1 '+' "a" == "+a+"
> example_wrap_2 = wrap 2 '+' "a" == "+a"
> example_wrap_3 = wrap 2 '+' "abcd" == "+ab+cd+"

Now I have some code that kinda works it just loops forever.

wrap _ _ [] = []
wrap n y xs = y : (insertAfter n xs)   where
    insertAfter 0 []     = y : wrap n y xs
    insertAfter m []     = []
    insertAfter m (x:xs) = x : insertAfter (m-1) xs

the basecase is never reached I understand as much. Why isnt it reached? Is the List Im passing the wrap function in the pattern of insertAfter not the reduced List after insertAfter has run trough it m times? Hints on how to solve this are appreciated or the solution too.

Thanks in advance.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
DillChude
  • 11
  • 1

1 Answers1

0

If we take a look at the variables, we see:

wrap _ _ [] = []
wrap n y xs = y : (insertAfter n xs)
  where
    insertAfter 0 []     = y : wrap n y xs
    insertAfter m []     = []
    insertAfter m (x:xs) = x : insertAfter (m-1) xs

Here the xs in y : wrap n y xs thus is the xs of the second wrap clause. But that thus means that the enumeration your insertAfter has done on the list does not matter. Because of the pattern, we know that at that point we reached the end of the list, so there is no need to call wrap n y xs anyway, we can simply stop with [y].

That will however not suffice, since it is also possible that m is 0, and the list is non-empty, thus (x:xs), in that case we should yield the character, and continue with the rest of the list.

Based on the specifications, for an empty string, we should still yield the y, since each string starts with y, so the basecase should be [y].

Combining these changes, we thus rewrite the function to:

wrap :: Integral n => n -> a -> [a] -> [a]
wrap _ y [] = [y]
wrap n y xs = y : (insertAfter n xs)
  where
    insertAfter 0 zs = wrap n y zs
    insertAfter m [] = []
    insertAfter m (z:zs) = z : insertAfter (m-1) zs

Usually it is better not to give variables the same name as the variables defined in the outer context, since it introduces confusion to what variable we are refering.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555