在尝试涉足函数式编程的过程中,我尝试学习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
这显然意味着我不知道我在做什么,并且不知何故搞砸了类型声明。
有人能给我指路吗?
1条答案
按热度按时间eh57zj3b1#
当你看到类似
Num (c -> c)
这样的编译器错误时,它与-XFlexibleContexts
或不正确的推断类型无关,它仅仅意味着你试图将某个不是函数的东西用作函数。“用作函数”只需要你有一个
f x
形式的表达式,其中f
和x
可以是任意的子表达式,这特别包括像(1+2)(3+4)
这样的表达式,它与假设你的意思是用并置来表示乘法。那么,就用乘法运算符吧!即
(1+2)*(3+4)
。您的代码还有另一个问题:你试图在实值表达式中使用索引变量,不像缺少乘法运算符,这是相当明智的,但是Haskell也不允许这样做,你需要显式地把积分 Package 在
fromIntegral
中。我强烈建议您对代码和类型进行重构。5元组非常模糊,您至少应该将
x,y,z
Package 为合适的向量类型。