Help with type definition

I am learning Ocaml by building a parser. I need help with how I can express below type definition in Ocaml. I have given an example from Haskell code.

data DurSecond = DurSecond Integer deriving (Eq, Ord, Show)
data DurMinute = DurMinute Integer (Maybe DurSecond) deriving (Eq, Ord, Show)
data DurHour = DurHour Integer (Maybe DurMinute) deriving (Eq, Ord, Show)
data DurTime = DurTimeHour DurHour
| DurTimeMinute DurMinute
| DurTimeSecond DurSecond deriving (Eq, Ord, Show)
data DurDay = DurDay Integer deriving (Eq, Ord, Show)
data DurWeek = DurWeek Integer deriving (Eq, Ord, Show)
data DurMonth = DurMonth Integer (Maybe DurDay) deriving (Eq, Ord, Show)
data DurYear = DurYear Integer (Maybe DurMonth) deriving (Eq, Ord, Show)
data DurDate = DurDateDay DurDay (Maybe DurTime)
| DurDateMonth DurMonth (Maybe DurTime)
| DurDateYear DurYear (Maybe DurTime) deriving (Eq, Ord, Show)

data Duration = DurationDate DurDate
| DurationTime DurTime
| DurationWeek DurWeek deriving (Eq, Ord, Show)

Leaving aside the deriving of instances which can be done with ppx_deriving, let me focus on the types themselves. In OCaml a lot of these types can be automatically derived from the same base type using the technique shown here: http://dev.realworldocaml.org/files-modules-and-programs.html#nested-modules

So e.g.

module type DURATION = sig
  type t
  val of_int : int -> t
  val to_int : t -> int
end

module Duration = struct
  type t = int
  let of_int = Fun.id
  let to_int = Fun.id
end

module Second : DURATION = Duration
module Day : DURATION = Duration
module Week : DURATION = Duration

type minute = int * Second.t option
type hour = int * minute option
type time = Hour of hour | Minute of minute | Second of Second.t
type month = int * Day.t option
type year = int * month option

type date =
| Day of Day.t * time option
| Month of month * time option
| Year of year * time option

type duration = Date of date | Time of time | Week of Week.t

A couple more notes about this approach:

  • The types that are purely ints get their own wrapper modules
  • Other types are defined as just pairs but they can be created unambiguously because their second elements expand out to the wrapped types
  • time, date, and duration are variants like in the Haskell code
1 Like