编写递归函数调整器
Write the recursive function adjuster
编写递归函数调整器。给定一个类型列表
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)
我是 haskell.I 的新人,非常感谢您的帮助。
您正在尝试在列表中的列表中构建列表,依此类推……
这是为什么?
(:) :: 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
可能会有帮助)。
这是另一种方法,没有错误处理
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
编写递归函数调整器。给定一个类型列表 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)
我是 haskell.I 的新人,非常感谢您的帮助。
您正在尝试在列表中的列表中构建列表,依此类推……
这是为什么?
(:) :: 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
可能会有帮助)。
这是另一种方法,没有错误处理
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