为什么这样的递归Haskell函数不起作用?

时间:2015-05-09 09:30:28

标签: haskell

以下是代码:

rep' :: Int -> a -> [a]
rep' 0 x = []
rep' n x = x:rep'(n-1, x)

我试着像这样重写它:

rep' :: Int -> a -> [a]
rep' 0 x = []
rep' n x = x:(rep' n-1 x)

但它也不起作用。

baby.hs:3:15-20: Couldn't match expected type ‘[a]’ with actual type ‘a0 -> [a0]’ …
    Relevant bindings include
      x :: a (bound at /Users/hanfeisun/Workspace/haskell/baby.hs:3:8)
      rep' :: Int -> a -> [a]
        (bound at /Users/hanfeisun/Workspace/haskell/baby.hs:2:1)
    Probable cause: ‘rep'’ is applied to too few arguments
    In the first argument of ‘(-)’, namely ‘rep' n’
    In the second argument of ‘(:)’, namely ‘(rep' n - 1 x)’
Compilation failed.
λ> 

有没有人有这方面的想法?

2 个答案:

答案 0 :(得分:10)

Haskell在错误消息中表达了它的问题和期望,比如

Prelude> :{
Prelude|     let
Prelude|     {
Prelude|         rep' :: Int -> a -> [a];
Prelude|         rep' 0 x = [];
Prelude|         rep' n x = x:rep' (n-1, x);
Prelude|     }
Prelude| :}

<interactive>:73:22:
    Couldn't match expected type `[a]' with actual type `a0 -> [a0]'
    In the return type of a call of rep'
    Probable cause: rep' is applied to too few arguments
    In the second argument of `(:)', namely `rep' (n - 1, x)'
    In the expression: x : rep' (n - 1, x)

<interactive>:73:27:
    Couldn't match expected type `Int' with actual type `(Int, a)'
    In the first argument of rep', namely `(n - 1, x)'
    In the second argument of `(:)', namely `rep' (n - 1, x)'
    In the expression: x : rep' (n - 1, x)

在第一部分中,

    Couldn't match expected type `[a]' with actual type `a0 -> [a0]'
    In the return type of a call of rep'
    Probable cause: rep' is applied to too few arguments

说,您已将rep'的返回类型声明为[a],但它返回a0 -> [a0],这意味着它返回了部分应用的函数。可能的问题也作为提示给你了

    Probable cause: rep' is applied to too few arguments

所以你可能会将更少的参数传递给函数rep'。在下一节中,行

    Couldn't match expected type `Int' with actual type `(Int, a)'

说它期待Int,但它得到(Int, a)。在Haskell中,当你说(n-1, x)时,它被视为一个元组对象,其中包含两个元素。因此,您实际上是使用单个元组对象调用rep',而不是两个参数。

要使用两个参数实际调用rep',您可以这样做

rep' n x = x:rep' (n-1) x

现在,您使用两个参数rep'(n-1)来呼叫x

Prelude> :{
Prelude|     let
Prelude|     {
Prelude|         rep' :: Int -> a -> [a];
Prelude|         rep' 0 x = [];
Prelude|         rep' n x = x:rep' (n-1) x;
Prelude|     }
Prelude| :}
Prelude> rep' 5 100
[100,100,100,100,100]

答案 1 :(得分:5)

rep'的第一个参数应为Int,但当您将其称为rep' (n-1, x)时,第一个也是唯一的参数是元组。