简体   繁体   English

定义数据类型时如何强制类型关系和约束

[英]How to enforce type relation and constraints when defing data type

In the following code:在以下代码中:

data Point = Point { x           :: Int, 
                     leftHeight  :: Int, 
                     rightHeight :: Int}
data Rectangle = Rec Point Point

rec1 = Rec p1 p2

There are several constraints when creating Rec such as:创建Rec时有几个限制,例如:

x p1 < x p2
(leftHeight p1 ) should always be zero
(rightHeight p2 ) should always be zero
rightHeight p1 == leftHeight p2

Is there a way to enforce these constraints at type level?有没有办法在类型级别强制执行这些约束? Because I'm using QuickCheck to generate some sample Rec but these contraints make QuickCheck very slow to generate random samples.因为我使用QuickCheck生成一些样本Rec但这些限制使QuickCheck生成随机样本的速度非常慢。

edit: I've solved the slow QuickCheck issue.编辑:我已经解决了 QuickCheck 缓慢的问题。 But anyway still curious if such constraint can be expressed in Haskell但无论如何仍然很好奇这种约束是否可以用 Haskell 表达

To point out the obvious, the standard way of enforcing these constraints at type level would be to define your Rectangle differently:指出显而易见的,在类型级别强制执行这些约束的标准方法是以不同的方式定义您的Rectangle

data Rectangle = Rec
  { x1 :: Int
  , x2 :: Int
  , height :: Int
  }

This enforces all constraints except "x1 < x2".这会强制执行除“x1 < x2”之外的所有约束。 You can use smart destructors to recreate the rectangle's Point "fields":您可以使用智能析构函数重新创建矩形的Point “字段”:

point1 :: Rectangle -> Point
point1 (Rec x1 _ h) = Point x1 0 h

point2 :: Rectangle -> Point
point2 (Rec _ x2 h) = Point x2 h 0

and define a smart constructor (which can also enforce the "x1 < x2" constraint):并定义一个智能构造函数(它也可以强制执行“x1 < x2”约束):

rect :: Point -> Point -> Rectangle
rect (Point x1 0 h1) (Point x2 h2 0) | h1 == h2 && x1 < x2 = Rec x1 x2 h1
rect _ _ = error "bad rectangle"

Seriously, this really is the best way to enforce constraints at the type level in Haskell!说真的,这确实是在 Haskell 中强制执行类型级别约束的最佳方式!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM