回答
您可以使用ExistentialQuantification
或GADTs
,但都不会做你想要的。您将永远无法使用两个Point2D
值进行算术运算。所有你知道的内容是,他们是一些 Num的实例。您正在告诉编译器放弃关于它们的所有其他信息。这意味着您要告诉编译器放弃任何可能具有的信息,即一对Point2D
值包含相同的类型。如果没有这些信息,您将无法对两个Point2D
的值进行任何算术运算。
这几乎肯定不是你想要的。例如,你不能写一个distance
函数。对于这种有限的类型你有什么可能的用途?关于你所能做的所有事情是把他们的内容转换为String
。
编辑:
我想我明白你在做什么。你只是想确保Point2D中的所有内容都是一个数字。我不认为你真的想要类型擦除。
在这种情况下,我会去与GADT版本,其中一个非常重要的变化:
{-# LANGUAGE GADTs #-}
data Point2D a where
Point :: (Num a) => a -> a -> Point2D a
这样做的最终结果是,你只能使用Point
构造具有相同的两个值Num的实例,但不会丢失类型。此外,由于使用了GADTs
,构造函数Point
上的模式匹配为您恢复了Num上下文,这基本上就是您期望的。
但我认为这里最重要的不是丢弃内容的类型。这样做使得该类型基本上不可能合作。
为数据成员恢复实例上下文似乎只在数据类型(使用`(Point a b)`或使用记录字段名称`Point {x = a,y = b}`)进行模式匹配时才起作用。但有什么办法可以让这个字段访问功能?也就是说,当用像`(x p)`这样的表达式来访问`Point`` p`时。 – Lii 2016-06-09 14:14:49
是,但您必须认识到约束的含义与通常的泛型不同。
通常情况下,像仿制药type Foo a = (a, a)
意味着
为各类
a
,Foo a
由两a
的
然而,在你的榜样,需要短语是不同的:
对于索姆e型
a
,Point2D
由两a
的
或
有一个类型
a
该Point2D
由
因此,通用的类型不是通用(适用于所有类型...),但是存在(它存在某种类型...)。在GHC,我们可以通过extenstion
{-# ExistentialQuantification #-}
在本article on the topic描述允许这样。您的代码,毕竟是
data Point2D = forall a . Num a => Point a a
{-# LANGUAGE GADTs #-}
data Point2D where
Point :: (Num a) => a -> a -> Point2D
当然!
这应该做你想要什么:
{-# LANGUAGE GADTs #-}
data Point2D a where
Point :: Num a => a -> a -> Point2D a
p :: Num a => a -> a -> Point2D a
p = Point
sumP :: Point2D a -> Point2D a -> a
sumP (Point a b) (Point c d) = a + b + c + d
您还可以使用existensials,但你不能做后它的模式匹配的数据什么。
- 1. 为通用参数指定构造函数约束
- 2. 指定类型约束约束
- 3. 类型参数构造函数签名约束
- 4. 在C#中有参数约束的泛型构造函数吗?
- 5. 工厂方法构造函数的类型约束
- 6. 约束 - 派生类必须有一个默认构造函数
- 7. 在子类构造函数中的接口类函数指针
- 8. 构造函数指向perl6中的类
- 9. 泛型类型的构造函数约束或只是检查我的泛型类型构造函数中的约束?
- 10. 与约束定制领域构造
- 11. 类构造函数中变量的命名约定
- 12. '对匹配指定绑定约束的类型的构造函数的调用引发异常
- 13. 您可以在类型约束参数上设置匹配构造函数吗?
- 14. 在构造函数中指定重复的泛型类型?
- 15. 如何在案例类中指定多个构造函数?
- 16. 构造具有度约束
- 17. 在C++类构造函数中的函数指针
- 18. 如何对构造函数的参数进行约束
- 19. 在构造函数上指定属性值
- 20. 为什么new()约束需要公共构造函数?
- 21. 设计指定的构造函数
- 22. 类构造函数
- 23. 如何指定继承类的构造函数定义?
- 24. 结构图构造函数参数注入约定
- 25. 构造函数和构造函数中不同类的成员值
- 26. 在父构造函数之前调用子类构造函数
- 27. 如何在构造函数外访问构造函数的值
- 28. 为什么没有办法在C#中约束构造函数的签名?
- 29. Microsoft Unity。如何在构造函数中指定某个参数?
- 30. Javascript类,构造函数和种子值
一般来说,最好将您的类型约束放在实际需要的地方。这不是数据类型,而是需要Num类型的方法,所以应该在那里声明。类型系统将负责其余部分。 – amccausl 2011-01-27 06:45:58