Reputation:
insert_at
insert an element e
into a list xs
in specific location n
test
getting Left
if n
less than 0
test2
getting Left
if n
larger than xs
's length or The type e
isn't match the element's type in listxs
. Otherwise passing Right xs
to the next.
import Data.Typeable
insert_at :: a -> [a] -> Int -> [a]
insert_at e xs n = a++(e:b) where
t = splitAt n xs
a = fst t
b = snd t
test :: (Ord a, Num a) => b -> a -> Either [Char] b
test xs n = if n < 0 then Left "n<0" else Right xs
test2 :: (Typeable a1, Typeable a2) =>
a1 -> [a2] -> Int -> Either [Char] [a2]
test2 e xs n
| n> ( length xs )= Left "n> $ length xs "
| (typeOf e) /= (typeOf (head xs) ) = Left "(typeOf e) /= (typeOf (head xs) ) "
|otherwise = Right xs
sf :: Typeable a => a -> [a] -> Int -> Either [Char] [a]
sf e xs n = test xs n >>test2 e xs n >> Right (insert_at e xs n)
All the other error got properly handled, expect this.
* No instance for (Num Char) arising from the literal `1'
* In the expression: 1
In the second argument of `sf', namely `[1, 2, 3, 4, ....]'
In the expression: sf 'a' [1, 2, 3, 4, ....] 3
Upvotes: 0
Views: 1009
Reputation: 80714
The error message states that you're trying to evaluate the expression sf 'a' [1, 2, 3, 4, ....] 3
. Since this expression is not shown in your question, I'm assuming you're using it in GHCi to test out your code, right?
The type signature of sf
says that the first parameter has type a
, and the second parameter has type [a]
, which is a list whose elements are of the same type as the first parameter.
So the compiler sees that the first parameter is 'a'
. That's a character, type Char
.
"Got it," - thinks the compiler, - "now I know that a
is Char
. And now I know that the second parameter must have type [Char]
- that is, a list of Char
".
And yes, the second parameter is indeed a list, but wait! The first element of the list is not a character, but number 1
! That does not compute!
Fortunately, number literals are special in Haskell. Number literals are not merely of type Int
or even of type Integer
, no! Numbers can be of any type as long as that type has an instance of class Num
.
So since the compiler already knows that the elements of that list must be of type Char
, but it sees a number literal, it concludes that it must now find an instance of class Num
for type Char
.
But there is no such instance! And so the compiler rightly complains: "no instance Num Char
"
To fix the problem, I need to better understand what you were actually trying to do.
Did you intend the whole function to work on numbers? Then the first parameter must be a number, not a character.
Or did you intend it to work on characters? Then the second parameter must be a list of characters, not numbers.
Or did you intend the first two parameters not to be the same type at all? Then you must change the type signature of sf
to indicate that.
Upvotes: 2
Reputation: 152682
sf
expects a value and a list as its first two arguments. The elements of the list must have the same type as the first argument. This is the meaning of
sf :: a -> [a] -> ...
When you write sf 'a' [1]
, this means 1
and 'a'
must have the same type. So the type checker looks for a way to interpret 1
as a Char
; it fails, because this is not possible. Some fixes might include:
sf 'a' "1234" 3
sf 'a' [toEnum 1, toEnum 2, toEnum 3, toEnum 4] 3
sf (fromEnum 'a') [1, 2, 3, 4] 3
Upvotes: 0