Stephen-Wisniewski
Stephen-Wisniewski

Reputation: 321

Why doesn't 'tail x : head x' work?

New to Haskell. Why does the following code not work? How do I concatenate the tail and the head like this?

func :: [String] -> [String]
func x = tail x:head x

Upvotes: 1

Views: 277

Answers (2)

Thomas M. DuBuisson
Thomas M. DuBuisson

Reputation: 64740

Lets work through the types to understand why this didn't work before we focus on the proper solution.

You presented:

func :: [String] -> [String]
func x = tail x:head x

We know:

tail x :: [String]
head x :: String
(:)    :: String -> [String] -> [String]
            ^          ^ the 'head' argument's position
            ^---the 'tail' argument's position

So clearly the types aren't matching up - a list where an element is expected and an element where a list is expected.

It's worth noting that there isn't any default snoc operator, which cons's an element to the end of a list. What you can do is append to lists via (++) :: [String] -> [String] -> [String]. Since the head xs isn't a [String] we could make it one via square brackets: [head xs].

More-over, the use of head and tail are not safe - they'll throw an exception if the list is empty. It is better to use pattern matching so the compiler can warn you about partial functions in addition to them being more visibly obvious. In this case we'd match the first element and the rest of the list:

func (firstElement : restOfList) = restOfList ++ [firstElement]

And looking at this it should be obvious func isn't yet defined for empty lists so we can add one more case:

func [] = []

Upvotes: 7

Stephen-Wisniewski
Stephen-Wisniewski

Reputation: 321

Solution:

Change

func :: [String] -> [String]
func x = tail x:head x

to

func :: [String] -> [String]
func x = tail x++[head x]

Upvotes: 0

Related Questions