重复功能N次错误

时间:2013-10-31 21:06:04

标签: haskell higher-order-functions

在haskell,我试过这个:

multi::(Num n)=>n->((a->a)->(a->a))
(multi 0) f x=x
(multi n) f x=(multi n-1) f (f x)

希望获得一个可以多次重复另一个函数的函数。 在ghci我得到了这个:

[1 of 1] Compiling Main             ( pad.hs, interpreted )

pad.hs:2:8:
    Could not deduce (Eq n) arising from the literal `0'
    from the context (Num n)
      bound by the type signature for
                 multi :: Num n => n -> (a -> a) -> a -> a
      at pad.hs:1:8-35
    Possible fix:
      add (Eq n) to the context of
        the type signature for multi :: Num n => n -> (a -> a) -> a -> a
    In the pattern: 0
    In an equation for `multi': multi 0 f x = x

pad.hs:3:23:
    Could not deduce (Num ((a -> a) -> a -> a))
      arising from a use of `-'
    from the context (Num n)
      bound by the type signature for
                 multi :: Num n => n -> (a -> a) -> a -> a
      at pad.hs:1:8-35
    Possible fix:
      add an instance declaration for (Num ((a -> a) -> a -> a))
    In the expression: multi n - 1
    In the expression: (multi n - 1) f (f x)
    In an equation for `multi': multi n f x = (multi n - 1) f (f x)
Failed, modules loaded: none.

我是哈斯克尔的新手。我该怎么办?

4 个答案:

答案 0 :(得分:4)

夫妻俩。您无法检查Num s是否相等。您可能正在寻找Int。其次,你不需要围绕multi和它的论证的parantheses。还有其他一些格式化。

multi :: Int -> (a -> a) -> a -> a
multi 0 f x = x
multi n f x = multi (n-1) f (f x)

你可以使这种类型的签名更通用,但我们会坚持这一点。但是你可以用更高阶函数来编写这整个事物。

multi :: Int -> (a -> a) -> a -> a
multi n f a = foldl (\v _ -> f v) a [1..n]

答案 1 :(得分:2)

你几乎做到了。最小的修复是在n - 1周围添加括号并删除签名:

(multi 0) f x=x
(multi n) f x=(multi (n-1)) f (f x)

答案 2 :(得分:2)

我可以对程序进行编译的最小变化是:

multi::(Eq n, Num n)=>n->((a->a)->(a->a))
(multi 0) f x=x
(multi n) f x=(multi (n-1)) f (f x)

Num类型类不要求成员已经是Eq的成员,因此我们也必须指定它。此外,我们希望将n-1作为参数传递给multi

此问题通常在Haskell土地上使用iterate!!完成。

答案 3 :(得分:1)

这里有一些错误。

Num n并不意味着Eq n,这意味着Eq n => Num n类型类定义中没有Num约束。要在0上进行模式匹配,您需要将n类型作为Eq的实例。我只是明确地将其更改为Int,没有理由在这段代码中有额外的一般性。

接下来,(multi n-1)multi应用于n,然后减去1。b我还清理了代码并将parens放在正确的位置。

multi:: Int -> (a -> a) -> a -> a
multi 0 _ x = x
multi n f x = multi (n-1) f (f x)

作为Cirdec points out,您可以使用iterate f a !! n执行此操作。

编辑:

如果您要执行的操作是获得f应用n次的功能,则可以执行此类操作。使用10n替换(1+)与您想要重复的任何功能。 (或仅部分应用multi

let f = foldr1 (.) (take 10 $ repeat (1+))