事实证明,图表包的annularWedge函数的内半径不能为0。您必须改为使用wedge

对我来说,内半径0只是annularWedge的简并情况,其行为应类似于wedge,因此我尝试将它们结合起来:

mywedge r2 r1 d a
  | r1 == 0   = wedge r2 d a
  | otherwise = annularWedge r2 r1 d a


当然,它不起作用,而且我无法弄清楚该错误是什么意思:

Non type-variable argument in the constraint: RealFloat (N t)
(Use FlexibleContexts to permit this)
When checking that ‘mywedge’ has the inferred type
  mywedge :: forall t.
             (RealFloat (N t), TrailLike t, V t ~ V2) =>
             N t -> N t -> Direction V2 (N t) -> Angle (N t) -> t


实际上,事实证明annularWedgewedge具有不同的约束,这使我感到惊讶:

annularWedge :: (TrailLike t, V t ~ V2, N t ~ n, RealFloat n) => n -> n -> Direction V2 n -> Angle n -> t

wedge :: (InSpace V2 n t, OrderedField n, TrailLike t) => n -> Direction V2 n -> Angle n -> t


那么,如何将这两个函数组合成一个合理的函数,该函数接受内部半径为0并做正确的事情?

最佳答案

解决方案很简单。正如ErikR所说,在文件顶部添加{-# LANGUAGE FlexibleContexts, TypeFamilies #-}。明确地说,这些都是要添加的安全扩展名(某些扩展名,例如重叠的实例或不确定的实例,应使您在启用它们之前先暂停一下,但这些扩展名mostly是安全的)

尽管并不明显,但wedge签名的约束严格弱于annularWedge的约束。

如果您对签名为何如此不同感到好奇,请继续阅读...

对于初学者来说,一旦找到约束,它们并没有什么不同。让我们从wedge开始。

(InSpace V2 n t, OrderedField n, TrailLike t)


查看InSpace的定义,您会发现它没有任何功能,实际上就像一个同义词:(V a ~ v, N a ~ n, Additive v, Num n) => InSpace v n a。然后,我们可以将InSpace V2 n t扩展为(V t ~ V2, N t ~ n, Additive V2, Num n)。同样,OrderedField只是(Floating n, Ord n)的简写。现在,wedge的约束看起来像

(TrailLike t, V t ~ V2, N t ~ n, Additive V2, Num n, Floating n, Ord n)


但是,事实证明,我们甚至可以删除Additive V2约束,因为在Additive的情况下该实例已定义为where Linear.Vector is defined in Num n并且Num n => Fractional n => Floating n是冗余的。这使我们对wedge的约束更加简单

(TrailLike t, V t ~ V2, N t ~ n, Floating n, Ord n)


看起来很像annularWedge的约束。实际上,唯一的区别是与wedge约束(Floating n, Ord n)相比,annularWedge约束RealFloat n。在这一点上,约束非常相似,因此值得研究wedge的代码。事实证明,wedge使用了在_theta中定义的HasTheta,并且corresponding V2 instance使用了反正切函数(在追逐了更多的依赖项之后才得到)。

10-06 02:44