Reputation: 369
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
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
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 Char
s, 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