Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何修复Haskell中的“非法类型签名”错误_Haskell - Fatal编程技术网

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

如何修复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

我在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 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的函数。