[英]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 = ...
此外,我认为在此处用f
, g
的变量来定义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
我们在这里定义了两个“帮助程序”函数helperf
和helperg
, helperf
将fx
与helperg (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]
制作了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
。
我们还对签名进行了概括:现在,我们可以使用任何数字类型a
,以及类型为f, g :: a -> a
的两个函数f
和g
f, g :: a -> a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.