Can
Can

Reputation: 369

Pattern x:xs with strings

I am quite new in Haskell world. I was reading the online http://learnyouahaskell.com but I could not understand a small detail about pattern-matching section. I have written those functions

myFunc' (firstLetter:_) = firstLetter -- returns firstLetter of given string

However if I do something like that

myFunc' (firstLetter:_) = "Hello" ++firstLetter

Gives me following error when I call this function

Couldn't match type ‘Char’ with ‘[Char]’
      Expected type: [[Char]]
        Actual type: [Char]

But if I modify the function like this

myFunc' (firstLetter:_) = "Hello" ++ [firstLetter]

That works fine when I call this function. I was wondering why do I need brackets in other cases. What is actually firstLetter.

Upvotes: 1

Views: 2490

Answers (2)

user2847643
user2847643

Reputation: 2935

First, if you check the type of (++) in ghci, you get:

Prelude> :t (++)
(++) :: [a] -> [a] -> [a]

That means it takes two lists of a's as arguments.

Likewise let's see what (:) does:

Prelude> :t (:)
(:) :: a -> [a] -> [a]

So the first argument of (:) need not be a list at all. If we fix a == Char we in fact get (:) :: Char -> String -> String.

We can define a function headStr (recall String == [Char]):

headStr :: String -> Char
headStr (x:_) = x
headStr _ = error "Empty string!"

Note that due to the type of (:) in this case x :: Char.

On the other hand if we try to define:

hello :: String -> String
hello (x:_) = "Hello" ++ x
hello _ = error "Empty string!"

it will not type check because in the non error case we get [Char] ++ Char. As ghci helpfully told us, the second argument to (++) must always be a list and in this case since the first argument is [Char] it must also be [Char].

As you noticed yourself, this can be fixed by wrapping x in a list:

hello' :: String -> String
hello' (x:_) = "Hello" ++ [x]
hello' _ = error "Empty string!"

and this works as expected.

Upvotes: 5

Rakete1111
Rakete1111

Reputation: 48958

"Hello ++ firstLetter

The types there are:

[Char] ++ Char

As you can see, that isn't possible. You can't add a Char to a [Char], they are different types!

But by doing

[firstLetter]

you are creating a list with 1 element, firstLetter. Because firstLetter is a Char, you'll get a list of Chars, i.e. the list is of type [Char].

Adding 2 lists of the same type is allowed, and that's why it works in the second case.

Upvotes: 4

Related Questions