我是哈斯凯尔的新手。我有两个问题,但它们有点相关。
是否可以定义一个不包括特定整数的整数类型,例如零。或者只是正数。
data allIntsButZero = ..? { a /= 0 | for all a in Int} ??
data positiveInts = ..? { a >= 0 | for all a in Int} ??
简而言之,我可以将类型定义为另一种类型的子集吗?
其次,我可以定义一个强加逻辑的类型吗? e.g。
type doublePair = (Int, Int * 2) {- where snd is always 2 times of fst -}
data validDDMMYYYY = G Int Int Int {- where complies to gregorian calendar -}
答案 0 :(得分:3)
type doublePair
这些确实没有意义。如果snd
始终是fst
的两倍,那么它实际上并不包含任何信息!所以,这种类型肯定更好地表达为
newtype DoubleableInt = DoubleableInt {getDoubleableInt :: Int}
其他人确实有道理,但我认为你仍然有点遗漏抽象点。类型validDDMMYYYY
可能应该表示 date ,即一个时间点。如何表示这不应该是用户的关注:如果某个库依赖于某种表示,它应该只提供专门的“智能构造函数”来确保良好的形成。像
newtype AllIntsButZero = AllIntsButZero {getNonzeroInt :: Int}
mkNonzeroInt :: Int -> Maybe AllIntsButZero
mkNonzeroInt 0 = Nothing
mkNonzeroInt n = AllIntsButZero n
然后,您可以拒绝导出AllIntsButZero
构造函数(这将允许用户形成错误的AllIntsButZero 0
):
module RestrictedNumbers (AllIntsButZero, getNonzeroInt, mkNonzeroInt) where
这样,用户只会将AllIntsButZero
视为“黑匣子”,而且可以使用它们的函数可以保证产生格式良好的值。