我试图很好地理解种类,类型&术语(或值,不知道哪个是正确的)以及用于操作它们的GHC扩展。我知道我们可以使用TypeFamilies来使用Types来编写函数,现在我们也可以在一定程度上使用DataKinds,PolyKinds等操作Kinds。我已经阅读了关于Singleton Types的这个paper,虽然我还没有完全理解,但它似乎很有趣。这一切都让我产生疑惑,是否有办法创建一个函数来计算基于期限或价值水平计算的回报类型?这是依赖类型实现的吗?作为术语或值计算的结果返回类型
这里的基础上研究了很多我在想什么
data Type1
data Type2
f :: Type1 -> Type2 -> (Type1 or Type2)--not using Either or some "wrapper" ADT
--update --------
一个例子,在这里帮助,它现在已经成为我清楚无论启用了多少个扩展,函数的返回类型都不能根据Haskell中的值级别的表达式进行计算。所以我发布了更多我的实际代码,希望有人能帮助我决定继续前进的最佳方式。我正在写一个圆锥曲线和二次曲面作为基本类型的小型库。这些类型的操作涉及计算它们之间的交点。 2个曲面的交点是圆锥曲线类型之一,其中包括类似于点的退化(实际上除了圆锥点外,实际上还需要另一种类型的曲线,但除此之外)。确切的曲线返回类型只能由运行时相交曲面的值决定。圆柱面 - 平面相交可以导致无,线,圆或椭圆。 我的第一个计划是使用ADT的像这样结构曲线和曲面...
data Curve = Point !Vec3
| Line !Vec3 !UVec3
| Circle !Vec3 !UVec3 !Double
| Ellipse !Vec3 !UVec3 !UVec3 !Double !Double
| Parabola !Vec3 !UVec3 !UVec3 !Double
| Hyperbola !Vec3 !UVec3 !UVec3 !Double !Double
deriving(Show,Eq)
data Surface = Plane !Vec3 !UVec3
| Sphere !Vec3 !Double
| Cylinder !Vec3 !UVec3 !Double
| Cone !Vec3 !UVec3 !Double
deriving(Show,Eq)
...这是最直接,最具有作为一个很好的封闭代数类型,这是我喜欢的优点。在这种表示中,交点的返回类型很简单,只是曲线。这种表示的缺点是这些类型的每个函数都必须为每种类型进行模式匹配,并处理所有对我来说很麻烦的排列。 Surface-Surface交叉函数将有16个模式匹配。
下一个选项是保持每个曲面和曲线类型不同。像这样,
data Point = Point !Vec3 deriving(Show,Eq)
data Line = Line !Vec3 !UVec3 deriving(Show,Eq)
data Circle = Circle !Vec3 !UVec3 !Double deriving(Show,Eq)
data Ellipse = Ellipse !Vec3 !UVec3 !UVec3 !Double !Double deriving(Show,Eq)
data Parabola = Parabola !Vec3 !UVec3 !UVec3 !Double deriving(Show,Eq)
data Hyperbola = Hyperbola !Vec3 !UVec3 !UVec3 !Double !Double deriving(Show,Eq)
data Plane = Plane !Vec3 !UVec3 deriving(Show,Eq)
data Sphere = Sphere !Vec3 !Double deriving(Show,Eq)
data Cylinder = Cylinder !Vec3 !UVec3 !Double deriving(Show,Eq)
data Cone = Cone !Vec3 !UVec3 !Double deriving(Show,Eq)
这似乎是它可能是从长远来看,更灵活,更是不错,粒状,但需要一个包装ADT能够从交叉功能处理多个返回类型,或建立一个一般“曲线”或“曲面”的列表,因为它们之间没有关系。我可以使用Type Classes和Existentials将它们分组,但是然后我失去了原来的类型,我不喜欢它。
在这些设计中的妥协使我试试这个..
---------------------------------------------------------------
-- Curve Types
---------------------------------------------------------------
type Pnte = Curve PNT
type Line = Curve LIN
type Circ = Curve CIR
type Elli = Curve ELL
type Para = Curve PAR
type Hype = Curve HYP
-----------------------------------------------
data CrvIdx = PNT
| LIN
| CIR
| ELL
| PAR
| HYP
-----------------------------------------------
data Curve :: CrvIdx → * where
Pnte :: !Vec3 → Curve PNT
Line :: !Vec3 → !UVec3 → Curve LIN
Circ :: !Vec3 → !UVec3 → !Double → Curve CIR
Elli :: !Vec3 → !UVec3 → !UVec3 → !Double → !Double → Curve ELL
Para :: !Vec3 → !UVec3 → !UVec3 → !Double → Curve PAR
Hype :: !Vec3 → !UVec3 → !UVec3 → !Double → !Double → Curve HYP
---------------------------------------------------------------
-- Surface Types
---------------------------------------------------------------
type Plne = Surface PLN
type Sphe = Surface SPH
type Cyln = Surface CYL
type Cone = Surface CNE
-----------------------------------------------
data SrfIdx = PLN
| SPH
| CYL
| CNE
-----------------------------------------------
data Surface :: SrfIdx → * where
Plne :: !Vec3 → !UVec3 → Surface PLN
Sphe :: !Vec3 → !Double → Surface SPH
Cyln :: !Vec3 → !UVec3 → !Double → Surface CYL
Cone :: !Vec3 → !UVec3 → !Double → Surface CNE
...起初我还以为是要给我一些神奇的,两全其美的情况,我可以指任何的曲线“(类似于列表或交集返回类型),并且还具有可用的完整类型(Curve CrvIdx),以使用多参数类型类等粒度样式编写函数。我很快发现这不会像我在这question中所显示的那样很好地工作。我顽固地继续将我的头靠在墙上试图找到一种方法来编写一个函数,该函数可以根据运行时参数的几何属性从我的GADT中选择返回类型,现在认识到这不会发生。所以现在问题是什么将是一种高效而灵活的方式来表示这些类型及其之间的相互作用?谢谢。
简而言之,**完全**依赖类型实现的类型:类型取决于一个术语(值)。 Haskell没有依赖类型,但Haskeller在为常见应用程序提供等效语义方面可以非常有创意。通常涉及一个或多个这些扩展。 – 2013-02-19 07:37:26