如何从Haskell的图表包中组合`annularWedge`和`wedge`?

时间:2016-08-08 19:05:23

标签: haskell haskell-diagrams

事实证明,图表包的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并做正确的事情?

2 个答案:

答案 0 :(得分:3)

解决方案很简单。正如ErikR所说,将{-# LANGUAGE FlexibleContexts, TypeFamilies #-}添加到文件的顶部。要清楚,这些都是添加的安全扩展(一些扩展,如重叠实例或不可判断的实例应该让您在启用它们之前暂停,但这些扩展是mostly安全的)

虽然不是很明显,但wedge签名的约束严格弱于annularWedge s约束。

如果您对签名看起来如此不同的原因感到好奇,请继续阅读......

对于初学者来说,一旦你追踪它们,约束就不会有所不同。让我们从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约束,因为该实例已定义为where Additive is defined in Linear.VectorNum 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中定义的int main() { if(number == 0) return -1; /* Here the rest of the program */ return 0; // End of program } HasTheta使用了一个反正切函数(在追逐几个依赖项之后你会得到)。

答案 1 :(得分:2)

请遵循GHC为您提供的建议:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}

import Diagrams
import Diagrams.TwoD.Arc

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

但总的来说,我喜欢在交易时使用<=比较 浮点数,即:

  | r1 <= 1e-10 = wedge r2 d 1