How can I add input checks to Haskell data constructors? Let's say I have
import Data.Time.Calendar
data SchedulePeriod = SchedulePeriod { startDate :: Day
, endDate :: Day
, accrualStart :: Day
, accrualEnd :: Day
, resetDate :: Day
, paymentDate :: Day
, fraction :: Double }
deriving (Show)
and I want to impose a constraint startDate < endDate
. Is there a way to do it without creating an abstract data type?
Data constructors are first class values in Haskell and actually have a type. For instance, the type of the Left constructor of the Either data type is: Left :: a -> Either a b. As first class values, they may be passed to functions, held in a list, be data elements of other algebraic data types and so forth.
Maybe is a type constructor, and its two possible data constructors are Nothing and Just . So you have to say Just 5 instead of Maybe 5 .
A data constructor is a "function" that takes 0 or more values and gives you back a new value. A type constructor is a "function" that takes 0 or more types and gives you back a new type.
In Haskell, the newtype declaration creates a new type from an existing one. For example, natural numbers can be represented by the type Integer using the following declaration: newtype Natural = MakeNatural Integer. This creates an entirely new type, Natural, whose only constructor contains a single Integer.
The standard way is to use a smart constructor that checks the precondition before creating the value, and to not export the real constructor it uses. Of course, this is creating an abstract data type, as you said.
The only way to achieve this without a smart constructor would be really evil type-system hackery (and you wouldn't be able to use the standard Day
type).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With