3

I want to create a Haskell function that prints the suffixes of a list:

The function should do the following:

> suffixes "123"
["23","3",""]
> suffixes "1"
[""]

I have written the following code:

suffixes :: [a] -> [[a]]
suffixes []         = [] : []
suffixes f@(_:t) = f: suffixes t 

The function prints the entered string or character as a suffix and I want to remove it so when I enter "123" it should print as above.

Can you help me solve this so that it does not print the entered string as a suffix.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
bob
  • 101
  • 8
  • 2
    If this was for homework or practice, then @WillemVanOnsem's answer seems like the right approach, but in actual code, you could consider writing `suffixes = tail . tails` using `tails` from `Data.List`. – K. A. Buhr Oct 07 '18 at 21:57

1 Answers1

4

There are basically two ways to do this. The first approach slightly changes how the function works: in that case the base-case returns an empty list, and the recursive case yields t instead of f:

suffixes :: [a] -> [[a]]
suffixes [] = []
suffixes (_:t) = t : suffixes t

This works since t is the tail of the list, so it is the list, but without the first element. We thus yield this element, and perform recursion on the tail t as well, until we reach the empty list. Since this empty list was already "yielded" by the recursive case, we thus do not yield it in the basecase.

Or we can just keep the old suffixes function (but rename it to for example go), and let the outer function "pre-processes" the list by "popping" an element:

suffixes :: [a] -> [[a]]
suffixes [] = []
suffixes (_:xs) = go xs
    where go [] = [] : []
          go f@(_:t) = f: go t

Note that for an empty string, there are no proper suffixes, hence we return an empty list.

This then yield the expected results:

Prelude> suffixes ""
[]
Prelude> suffixes "a"
[""]
Prelude> suffixes "ab"
["b",""]
Prelude> suffixes "abc"
["bc","c",""]
Prelude> suffixes "123abc"
["23abc","3abc","abc","bc","c",""]
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • `\(a:t) -> t:t` doesn't type check, though. – schuelermine Oct 10 '18 at 12:36
  • @MarkNeu: but here it is `a@(_:t) -> a : f t`, where `f` has type `[a] -> [[a]]`. I do not see where this lambda expression is used. It is normall that `\(_:_) -> t:t` does not type check, since `(:)` requires an element, and a list of these elements. Now `t` can not be an element, and a list of such elements at the same time. – Willem Van Onsem Oct 10 '18 at 12:41