I have written this small function to retrieve the tail of a list:
let getTail l = if length l > 0 then tail l else "empty list"
Passing []
to getTail
returns empty list
but passing [1,2,3]
gives the following error:
<interactive>:1:14:
No instance for (Num Char)
arising from the literal `3'
Possible fix: add an instance declaration for (Num Char)
In the expression: 3
In the first argument of `getTail', namely `[1, 2, 3]'
In the expression: getTail [1, 2, 3]
I can't understand what that error means. What is the problem? Using GHCi 7.0.4
Let's think about the type of your getTail
function. Initially, we can imagine l
to be any list. The return type, however, has to be a String
because you sometimes return "empty list"
. Since that's part of an if statement where you might also return tail l
, it means l
has to be a String
.
So your getTail
function has type String -> String
.
When you call getTail
with [1,2,3]
, it expects a String
, which is just a [Char]
. Remember that numeric literals are overloaded: [1,2,3]
is equivalent to calling [fromInteger 1, fromInteger 2, fromInteger 3]
. So, given this list, Haskell is trying to get a number from a Char
. Since Char
s are not part of the Num
class, this fails, giving you your error.
A good solution would be to return a Maybe
type and give Nothing
for the error rather than returning "empty list"
. So rewrite your function as:
let getTail l = if length l > 0 then Just (tail l) else Nothing
Now its type is [a] -> Maybe [a]
. Using this will force anybody using your function to check whether getTail
succeeded before being able to use the result.
Another option is to return []
in place of "empty list". In this case, your getTail
function will work exactly like drop 1
.
Prelude> let getTail l = if length l > 0 then tail l else "empty list"
You didn't give getTail
a type signature, so one is inferred.
Prelude> :t getTail
getTail :: [Char] -> [Char]
:t
gives you the type of anything in GHCi. This is extremely useful. Type signatures say a lot about a function in Haskell.
This is probably not what you meant. Why does it only work on [Char]
, (or equivalently, String
), and not on any list?
Here's why:
A function can only have one return type. Since you return "empty list"
when the list is empty, the return type must be String
. It just so happens that the return type of tail xs
where xs
is a [Char]
is also a String
, which is why you don't get an error when you first define the function. Therefore your function as it is must be [Char] -> [Char]
.
You're trying to call it with the argument [1, 2, 3]
, which has a type of Num a => a
. GHC is telling you "A Char
doesn't have an instance of Num", or "I can't turn a number into a Char." This involves typeclasses—if you don't understand those yet, it doesn't matter, because you would still get an error of you tried getTail ([1, 2, 3] :: [Int])
. You're trying to pass a list of Int
s to a function that takes a list of Char
s.
I would recommend reading through LYAH to understand the Haskell type system.
Should be rather []
instead of "empty list"
(You are mixing types)
Prelude> let getTail l = if length l > 0 then tail l else []
Prelude> getTail [1, 2, 3]
[2,3]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.