如何修复Haskell中的“非法类型签名”错误

时间:2019-05-06 19:12:49

标签: haskell

我在Haskell中遇到以下错误: “仅在具有ScopedTypeVariables的模式中允许类型签名” 我应该如何重用已定义的变量。预先感谢

 sum :: (Double -> Double) -> (Double -> Double) -> Int -> 
    (Double -> Double)
 sum f g n = (\x -> helper f g n x)
  where
   helper :: (Double -> Double) -> (Double -> Double) -> Int -> Double -> 
   Double
    |n == 0 = 0
    |mod n 2 == 1 = f(x) + helper f g n-1 f(x)
    |otherwise = g(x) + helper f g n-1 g(x)

1 个答案:

答案 0 :(得分:5)

这实际上看起来更像是一个语法错误:您从未为helper定义函数 body ,确实定义了helper的签名,后跟了警卫({ {1}}部分,但您应再次声明| ...

此外,我认为在此处为helper f g n x = ...和变量helper定义变量f是没有用的,因为在整个递归过程中这些变量都是固定的。

您可以将函数定义为:

g

我们在这里定义了两个“辅助”函数sumfg :: (Double -> Double) -> (Double -> Double) -> Int -> Double -> Double sumfg f g = helperf where helperf 0 _ = 0 helperf i x = let fx = f x in fx + helperg (i-1) fx helperg 0 _ = 0 helperg i x = let gx = g x in gx + helperf (i-1) gxhelperfhelperghelperff x进行汇总,而helperg (i-1) (f x)相同,除了我们使用helperg代替g。因此,我们在这里使用相互递归来解决问题。

但是,通过使用scanl :: (b -> a -> b) -> b -> [a] -> [b]take :: Int -> [a]sum :: Num a => [a] -> a,我们可以更优雅地解决此问题:

f

因此,我们在此创建sumfg :: Num a => (a -> a) -> (a -> a) -> Int -> a -> a sumfg f g n x = sum (take n (scanl (flip ($)) (f x) (cycle [g, f])))g的无限列表,就像f[g, f, g, f, g, f, ...]一样。然后,每次将累加器应用于其中一个函数时,我们就使用cycle [f, g]并产生该元素。我们将列表中的前scanl (flip ($))个项与n一起使用,最后使用take n来汇总这些值。

例如:

sum

由于Prelude> sumfg (2+) (3*) 5 1 91 (2+1) + (3*(2+1)) + (2+(3*(2+1))) + (3*(2+(3*(2+1)))) + (2+(3*(2+(3*(2+1)))))

我们还概括了签名:现在,我们可以使用类型为91的两个函数af的任何数字类型g