Haskell类型系统初学者:“约束中的Haskell非类型变量参数”错误

6ss1mwsb  于 2023-02-13  发布在  其他
关注(0)|答案(1)|浏览(145)

在尝试涉足函数式编程的过程中,我尝试学习Haskell,但遇到了一些类型系统的心理问题。
运行下面的代码会给出正确的输出(例如,生成以Angular theta环绕半径为R的圆柱体的圆的坐标):

coilGeneration_AngleTest housingRadius coilWidth coilDepth numEle zoffset centralAngle
     = [ (x',y',z)
       | theta <- [0,2*pi/(numEle-1)..2*pi]
       , let x = housingRadius * cos(coilWidth*cos(theta)/housingRadius)
       , let y = housingRadius * sin(coilWidth*cos(theta)/housingRadius)
       , let z = coilDepth * sin(theta)+zoffset
       , let x' = x * cos(centralAngle) - y * sin(centralAngle)
       , let y' = x * sin(centralAngle) + y * cos(centralAngle)
       ]

Sample coilGeneration_AngleTest function output
然而,试图将其推广到一个函数中,该函数生成在极轴和z轴方向上具有不同重叠的任意NxM圆阵列,通过运行:

coilArrayGeneration_Test r nE width depth n m mu gam
     = [ (x',y',z',i,j)
       | theta <- [0,2*pi/(nE-1)..2*pi]
       , i <- [1..n]
       , j <- [1..m]
       , let a = width/2
       , let b = depth/2
       , let x = r * cos(a*cos(theta)/r)
       , let y = r * sin(a*cos(theta)/r)
       , let z = b * sin(theta)
       , let phi = (2*i-1-n)((a-mu)/r)
       , let zo = (2*j-1-m)(b-gam)
       , let x' = x * cos(phi) - y * sin(phi)
       , let y' = x * sin(phi) + y * cos(phi)
       , let z' = z + zo
       ]

给出以下错误:

Build profile: -w ghc-9.2.5 -O1
In order, the following will be built (use -v for more details):
 - Haskell-0.1.0.0 (exe:Haskell) (file app/Main.hs changed)
Preprocessing executable 'Haskell' for Haskell-0.1.0.0..
Building executable 'Haskell' for Haskell-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /Users/zack/Desktop/Udemy/Haskell/dist-newstyle/build/aarch64-osx/ghc-9.2.5/Haskell-0.1.0.0/x/Haskell/build/Haskell/Haskell-tmp/Main.o )

app/Main.hs:66:1: error:
    • Non type-variable argument in the constraint: Num (c -> c)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        coilArrayGeneration_Test :: forall {c}.
                                    (Floating c, Num (c -> c), Enum c, Enum (c -> c)) =>
                                    c
                                    -> c
                                    -> c
                                    -> c
                                    -> (c -> c)
                                    -> (c -> c)
                                    -> c
                                    -> c
                                    -> [(c, c, c, c -> c, c -> c)]
   |
66 | coilArrayGeneration_Test r nE width depth n m mu gam = [(x',y',z',i,j)|theta <- [0,2*pi/(nE-1)..2*pi],....

Failure Output
在谷歌上搜索了一段时间后,我的函数似乎有一个编译器暗示的不正确的类型,但不幸的是,我对Haskell类型定义的理解还不足以修复它。我试图按照我看到的方式定义类型,即:

  • r-〉双精度
  • nE-〉内部
  • 宽度-〉双精度
  • 深度-〉双倍
  • n-〉整数
  • m-〉整数
  • mu-〉双倍
  • 游戏-〉双打
  • x '-〉双精度
  • y '-〉双精度
  • z '-〉双精度
  • I-〉内部
  • j-〉整数

获取:

coilArrayGeneration_Test :: (Floating a, Integral b) => a -> b -> a -> a -> b -> b -> a -> a -> [(a,a,a,b,b)]
coilArrayGeneration_Test r nE width depth n m mu gam
      = [ (x',y',z',i,j)
        | theta <- [0,2*pi/(nE-1)..2*pi]
        , i <- [1..n]
        , j <- [1..m]
        , let a = width/2
        , let b = depth/2
        , let x = r * cos(a*cos(theta)/r)
        , let y = r * sin(a*cos(theta)/r)
        , let z = b * sin(theta)
        , let phi = (2*i-1-n)((a-mu)/r)
        , let zo = (2*j-1-m)(b-gam)
        , let x' = x * cos(phi) - y * sin(phi)
        , let y' = x * sin(phi) + y * cos(phi)
        , let z' = z + zo
        ]

但这会抛出一大堆错误:
Errors after Type Declaration
这显然意味着我不知道我在做什么,并且不知何故搞砸了类型声明。
有人能给我指路吗?

eh57zj3b

eh57zj3b1#

当你看到类似Num (c -> c)这样的编译器错误时,它与-XFlexibleContexts或不正确的推断类型无关,它仅仅意味着你试图将某个不是函数的东西用作函数。
“用作函数”只需要你有一个f x形式的表达式,其中fx可以是任意的子表达式,这特别包括像(1+2)(3+4)这样的表达式,它与

let f = 1 + 2
         x = 3 + 4
     in f x

假设你的意思是用并置来表示乘法。那么,就用乘法运算符吧!即(1+2)*(3+4)
您的代码还有另一个问题:你试图在实值表达式中使用索引变量,不像缺少乘法运算符,这是相当明智的,但是Haskell也不允许这样做,你需要显式地把积分 Package 在fromIntegral中。

coilArrayGeneration_Test r nE width depth n m μ γ
      = [ (x',y',z',i,j)
        | ϑ <- [0, 2*pi/fromIntegral(nE-1) .. 2*pi]
        , i <- [1..n]
        , j <- [1..m]
        , let a = width/2
              b = depth/2
              x = r * cos(a*cos ϑ/r)
              y = r * sin(a*cos ϑ/r)
              z = b * sin ϑ
              φ = fromIntegral(2*i-1-n) * ((a-μ)/r)
              z₀ = fromIntegral(2*j-1-m) * (b-γ)
              x' = x * cos φ - y * sin φ
              y' = x * sin φ + y * cos φ
              z' = z + z₀
        ]

我强烈建议您对代码和类型进行重构。5元组非常模糊,您至少应该将x,y,z Package 为合适的向量类型。

相关问题