编写递归函数调整器

时间:2016-11-04 23:43:58

标签: haskell recursion functional-programming higher-order-functions

编写递归函数调整器。给出一个类型列表 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)

我是哈斯克尔的新人。我真的很感激一些帮助。

2 个答案:

答案 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