insert_at
将元素e
插入到特定位置xs
的列表中n
test
如果n
小于 0 则Left
test2
n
大于xs
的长度或e
的类型与列表xs
中的元素类型不匹配,则会Left
。否则Right xs
传递给下一个。
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)
所有其他错误都得到了妥善处理,期待这个。
* 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
错误消息指出您正在尝试计算表达式sf 'a' [1, 2, 3, 4, ....] 3
。由于您的问题中未显示此表达式,因此我假设您在GHCi中使用它来测试您的代码,对吗?
sf
的类型签名表示第一个参数的类型为a
,第二个参数的类型为[a]
,这是一个列表,其元素与第一个参数的类型相同。
所以编译器看到第一个参数是'a'
。这是一个角色,键入Char
.
知道了,"-编译器想,-"现在我知道a
是Char
.现在我知道第二个参数必须具有类型[Char]
- 即Char
列表"。
是的,第二个参数确实是一个列表,但是等等!列表的第一个元素不是字符,而是数字1
!这不算!
幸运的是,数字文字在哈斯克尔中很特别。数字文字不仅仅是Int
类型,甚至不是Integer
类型,不!数字可以是任何类型的,只要该类型具有类Num
的实例。
因此,由于编译器已经知道该列表的元素必须是类型Char
,但它看到一个数字文字,它得出结论,它现在必须找到类型Char
的类Num
的实例。
但是没有这样的例子!因此,编译器正确地抱怨:">没有实例Num Char
">
为了解决这个问题,我需要更好地了解你实际想要做什么。
您是否打算将整个函数用于数字?然后,第一个参数必须是数字,而不是字符。
还是你打算让它在角色上工作?然后,第二个参数必须是字符列表,而不是数字。
还是您打算将前两个参数根本不是同一类型?然后,您必须更改sf
的类型签名以指示这一点。
sf
需要一个值和一个列表作为其前两个参数。列表的元素必须与第一个参数具有相同的类型。这就是意思
sf :: a -> [a] -> ...
当你写sf 'a' [1]
时,这意味着1
和'a'
必须具有相同的类型。因此,类型检查器寻找一种将1
解释为Char
的方法;它失败了,因为这是不可能的。一些修复可能包括:
sf 'a' "1234" 3
sf 'a' [toEnum 1, toEnum 2, toEnum 3, toEnum 4] 3
sf (fromEnum 'a') [1, 2, 3, 4] 3