我正在处理一个函数,该函数用0填充Num列表,直到它至少与请求的长度一样长。
main = do
putStrLn $ show ( padList [1,2,3] 5)
padList :: (Num a) => [a] -> a -> [a]
padList x len = if length(x) >= len then x else padList ((x ++ 0) len)
但我一直在接受:
prog.hs:9:49:
Couldn't match expected type `[a]'
with actual type `Integer -> [Integer]'
In the return type of a call of `padList'
Probable cause: `padList' is applied to too few arguments
In the expression: padList (([0] : x) len)
In the expression:
if length (x) >= len then x else padList ((x ++ 0) len)
有人能指出我正确的方向吗?
我试图将x附加到列表[0],直到我得到:
[1,2,3,0,0]
但是,我的列表可能是浮动的,所以: [1.0,2.0,3.0]可能会变成=> [1.0,2.0,3.0,0.0,0.0]
我不太关心性能,我只是想学习函数式编程。
由于
答案 0 :(得分:3)
以下是如何修复它:
padList :: (Num a) => [a] -> Int -> [a]
^^^
padList x len = if length(x) >= len then x else padList ([0] ++ x) len
^^^^^^^^^^
表达式([0]:x)
表示x是列表,[0]
表示x的元素。也就是说,x是Ints列表的列表。
表达式[0] ++ x
表示[0]
和x
都是相同类型的列表,即两者都是Ints列表。或者,您可以使用(0:x)
。
此外,length x
会返回一个Int,而非一般Num a
,因此您无法使用a
作为第二个参数的类型。
答案 1 :(得分:1)
这里有一些问题,所以让我们分解一下:
padList :: (Num a) => [a] -> a -> [a]
padList x len = if length(x) >= len then x else padList ((x ++ 0) len)
长度类型为length :: [a] -> Int
,因此在比较length x >= len
时强制len
为Int
类型。由于需要更具体的类型,因此您声明的内容将引发错误。这可以通过更改类型签名来修复。
padList :: (Num a) => [a] -> Int -> [a]
现在类型正确,但功能仍然不正确。 (++)
的类型是(++) :: [a] -> [a] -> [a]
,这意味着它期望所有元素都是相同的类型。
如果您要定义功能
padList x len = if length(x) >= len then x else padList (x ++ 0) len
没有类型签名,由于Num
类型类,编译器实际上除了它之外。但推断类型为Num [a] => [a] -> Int -> [a]
这是因为您在执行(x++0)
时实际执行的操作我的x
类型为[a]
而0
类型为Num a => a
(++)
所以,如果我能够对这两个项目使用Num [a] => a
,那么[0]
必须有一个Num实例。这肯定不是你想要的。
相反,您想要将x
的列表添加到padList x len = if length(x) >= len then x else padList ((x ++ [0]) len)
:
`padList' is applied to too few arguments
现在回答你的原始问题,你得到的错误
((x ++ [0]) len)
是因为您的额外括号使编译器认为(x ++ [0])
是一个参数,它认为您将len
应用于padList x len = if length(x) >= len then x else padList (x ++ [0]) len
。你不想要括号
length(x)
也需要length x
周围的那个,你可以做{{1}}