编写递归函数调整器。给出一个类型列表 x,一个int和一个x类型的元素,要么从前面移除 列表,直到它与int的长度相同,或附加到列表的末尾 直到它的长度与int。
指定的值相同预期:
adjuster [1..10] (-2) 2 -> *** Exception: Invalid Size
adjuster [1..10] 0 2 -> []
adjuster "apple" 10 ’b’ -> "applebbbbb"
adjuster "apple" 5 ’b’ -> "apple"
adjuster "apple" 2 ’b’ -> "le"
adjuster [] 3 (7,4) -> [(7,4),(7,4),(7,4)]
我做了什么:
adjuster (x:xs) count b
| count < 0 = error "Invalid Size"
| count == 0 = []
| count < length xs = adjuster xs (count-1) b
| otherwise = (adjuster xs (count-1) b):b
我得到的错误:
* Occurs check: cannot construct the infinite type: t ~ [t]
Expected type: [t]
Actual type: [[t]]
* In the expression: (adjuster xs (count - 1) b) : b
In an equation for `adjuster':
adjuster (x : xs) count b
| count < 0 = error "Invalid Size"
| count == 0 = []
| count < length xs = adjuster xs (count - 1) b
| otherwise = (adjuster xs (count - 1) b) : b
* Relevant bindings include
b :: [[t]] (bound at code01.hs:21:23)
adjuster :: [a] -> Int -> [[t]] -> [t] (bound at code01.hs:21:1)
我是哈斯克尔的新人。我真的很感激一些帮助。
答案 0 :(得分:1)
您正在尝试在列表中的列表中构建列表,依此类推......等等。
(:) :: a -> [a] -> [a]
冒号运算符将一个元素和一个这样的元素列表作为参数,并从中构造一个列表(通过预先添加该元素)。
如果(adjuster ...)
的类型为[a]
,则b
必须为[[a]]
类型,第4行与最终结果相同,但第3行说类型是[a]
- 这是不同的。这就是GHC试图告诉你的。
首先,向每个顶级函数添加类型签名总是一个好建议:
adjuster :: [a] -> Int -> a -> [a]
应该清理你的错误信息,并在实现你的功能时保持诚实。
那么如何解决这个问题: - 您可以使用b:adjuster xs (count-1) b
但这会产生错误顺序的结果 - 所以
选择一个不同的运算符:(++)
并将b
包装在列表中。
| otherwise = (adjuster xs (count-1) b)++[b]
现在再提几点:
-Wall
- 这会告诉您错过了adjuster [] ..
的案例。length
是一项相对昂贵的操作 - 因为它需要遍历要计算的完整列表。length
,但仅使用基本情况[]
表示列表,0
表示count
(此处为函数) replicate
可能会有帮助。)答案 1 :(得分:0)
这是另一种方法,没有错误处理
adjuster xs n v = tnr n $ (++) (replicate n v) $ tnr n xs
where tnr n r = take n $ reverse r
如果您使用签名,也许更干净
adjuster n v = tnr . (++) (replicate n v) . tnr
where tnr = take n . reverse