如何修复Haskell中的“非法类型签名”错误
我在Haskell中遇到以下错误: 类型签名仅允许在具有ScopedTypeVariables的模式中使用 我应该如何重新使用定义的变量。提前谢谢如何修复Haskell中的“非法类型签名”错误,haskell,Haskell,我在Haskell中遇到以下错误: 类型签名仅允许在具有ScopedTypeVariables的模式中使用 我应该如何重新使用定义的变量。提前谢谢 sum :: (Double -> Double) -> (Double -> Double) -> Int -> (Double -> Double) sum f g n = (\x -> helper f g n x) where helper :: (Double -> D
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 f g n x= 此外,我不认为在这里用f的变量定义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-1fx相加,helperg也会这样做,只是我们用g代替f。因此,我们在这里使用相互递归来解决这个问题
但是,我们可以通过利用和更优雅地解决此问题:
在这里,我们这样做了一个g和f的无限列表,像[g,f,g,f,g,f,…]和循环[f,g]。然后,每次将累加器应用于其中一个函数时,我们都使用scanl flip$,并生成该元素。我们用take n取该列表的前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的两个函数f和g,g::a->a。这实际上看起来更像是一个语法错误:您从未为helper定义函数体,实际上您定义了helper的签名,后面是|。。。部分,但您应该再次声明helper f g n x= 此外,我不认为在这里用f的变量定义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-1fx相加,helperg也会这样做,只是我们用g代替f。因此,我们在这里使用相互递归来解决这个问题
但是,我们可以通过利用和更优雅地解决此问题:
在这里,我们这样做了一个g和f的无限列表,像[g,f,g,f,g,f,…]和循环[f,g]。然后,每次将累加器应用于其中一个函数时,我们都使用scanl flip$,并生成该元素。我们用take n取该列表的前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的两个函数f和g,g::a->a.,通过提供合法签名:。您可以删除helper函数的签名,事实上,您现在没有使用函数体本身定义子句。此外,尽管不是严格必需的,但我强烈建议您将variabel命名为与sum不同的名称,因为前奏曲已包含名为sum的函数。通过提供合法签名:。您可以删除helper函数的签名,事实上现在您没有用函数体本身定义子句。此外,尽管不是严格必需的,但我强烈建议您将variabel命名为与sum不同的名称,因为Prelude已经包含一个名为sum的函数。