繁体   English   中英

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

[英]How to fix “Illegal type signature” error in 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)

这实际上看起来更像是一个语法错误:您从未定义过用于helper的函数 ,的确定义了helper的签名,后跟了警卫( | ...部分),但是您应该再次声明helper fgnx = ...

此外,我认为在此处用fg的变量来定义helper是没有用的,因为在整个递归过程中这些保持不变。

您可以将函数定义为:

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) gx

我们在这里定义了两个“帮助程序”函数helperfhelperghelperffxhelperg (i-1) (fx) helperg ,并且helperg进行相同的操作,只是我们使用g而不是f 因此,我们在这里使用相互递归来解决问题。

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

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])))

因此,在这里,我们用cycle [f, g]制作了gf的无限列表,例如[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

我们还对签名进行了概括:现在,我们可以使用任何数字类型a ,以及类型为f, g :: a -> a的两个函数fg f, g :: a -> a

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM