Reputation: 513
I'm new to haskell. I've two questions but they're somewhat related.
Is it possible to define a type of Integers excluding specific integers for example zero. Or just positive numbers.
data allIntsButZero = ..? { a /= 0 | for all a in Int} ??
data positiveInts = ..? { a >= 0 | for all a in Int} ??
In short, can I define a type as a subset of another type?
Secondly, can i define a type where there is a logic imposed? 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 -}
Upvotes: 0
Views: 105
Reputation: 120711
The type doublePair
of these really doesn't make sense. If the snd
is always twice the fst
, then it doesn't actually contain any information! So, this type is definitely better expressed as
newtype DoubleableInt = DoubleableInt {getDoubleableInt :: Int}
The others do make some sense, but I think you're still a bit missing the point of an abstraction. The type validDDMMYYYY
is probably supposed to express a date, i.e. a point in time. How it respresents this shouldn't really be the user's concern: if a library depends on a certain representation, it should simply should offer specialised “smart constructors” to ensure well-formedness. Like
newtype AllIntsButZero = AllIntsButZero {getNonzeroInt :: Int}
mkNonzeroInt :: Int -> Maybe AllIntsButZero
mkNonzeroInt 0 = Nothing
mkNonzeroInt n = AllIntsButZero n
You may then refuse to export the AllIntsButZero
constructor (which would allow users to form incorrect AllIntsButZero 0
):
module RestrictedNumbers (AllIntsButZero, getNonzeroInt, mkNonzeroInt) where
This way, users will only see AllIntsButZero
as a “black box”, and the functions they can use with it are guaranteed to yield well-formed values.
Upvotes: 3