Haskell类型系统入门:解决‘非类型变量约束参数’错误
Haskell类型系统错误排查:多线圈坐标生成函数的问题
可正常运行的单线圈生成代码
下面的代码可以生成环绕半径为R的圆柱体、角度为theta的圆的坐标:
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) ]
多线圈数组生成函数的错误尝试
尝试推广为生成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],....
手动添加类型声明后的错误
根据自己理解的类型手动声明:
- r -> Double
- nE -> Int
- width -> Double
- depth -> Double
- n -> Int
- m -> Int
- mu -> Double
- gam -> Double
- x' -> Double
- y' -> Double
- z' -> Double
- i -> Int
- j -> Int
修改后的代码:
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 ]
但仍然出现大量类型不匹配的错误。
问题分析与修复
核心错误并非类型声明,而是语法错误导致的类型推断混乱:
在Haskell中,(2*i-1-n)((a-mu)/r) 会被解析为「将(a-mu)/r作为参数传入函数(2*i-1-n)」,但实际需要的是乘法运算,Haskell中乘法必须显式使用*运算符,不能像其他语言那样直接写在一起。
同时,i、j、nE是整数类型,需要转换为浮点数才能和其他浮点数值运算,避免类型不匹配。
最终修复后的完整代码:
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/(fromIntegral 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 = fromIntegral (2*i-1-n) * ((a-mu)/r) , let zo = fromIntegral (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 ]
这样修改后,代码的类型就能匹配手动声明,编译错误也会消失。
内容的提问来源于stack exchange,提问作者ztth222
相关产品推荐
相关产品推荐

