Data types

Data organization and data types

Imagine that we’re doing a study on communication patterns between students at a particular higher education institution. We have data on text messages: the sender, recipient, day of week, and time sent (hour and minute) for a number of messages (we don’t have the message contents, so as to preserve some modicum of privacy). How should we store these data?

We could imagine having a table:

sender :: String recipient :: String day :: String time :: ?
“4015551234” “8025551234” “Mon” ???

What should we use as the type of the time column? What would its values look like? We could imagine a number of possibilities:

  • String, such as "4:55"
  • Number, representing minutes or seconds since midnight
  • Multiple columns representing hours and minutes

There are tradeoffs between using a single column and using multiple columns:

  • If we use multiple columns, we can access the components independently
  • If we use a single column, all of the “time” data are in one place
  • Others?

Pyret (like most languages) provides a feature we can use to resolve this tradeoff: custom data types! Let’s take a look at how we could define a time data type:

data TimeData:
  | time(hour :: Number, minute :: Number)
end

We can call time to build times:

>>> noon = time(12, 0)
>>> half-past-three = time(3, 30)
>>> noon.hour
12
>>> half-past-three.minute
30

A data type has several parts:

name
The name of the data type (TimeData)
constructor
a function that builds the data type (time)
components
the parts of the data (hour, minute)

So now our table looks like:

sender :: String recipient :: String day :: String time :: TimeData
“4015551234” “8025551234” “Mon” time(2, 55)

We can write functions over data types:

fun appropriate-brunch-time(tm :: TimeData) -> Boolean:
  doc: "returns true if tm is an appropriate time to eat brunch"
  (tm.hour > 9) and (tm.hour < 13)
where:
  appropriate-brunch-time(time(0, 0)) is false
  appropriate-brunch-time(time(12, 0)) is true
  appropriate-brunch-time(time(8, 59)) is false
end

How would we write an earlier function?

fun earlier(tm1 :: TimeData, tm2 :: TimeData) -> Boolean:
  ...
where:
  earlier(time(0, 0), time(0, 1)) is true
  earlier(time(0, 1), time(1, 0)) is true
  earlier(time(1, 3), time(1, 2)) is false
  earlier(time(1, 0), time(0, 3)) is false
end

We’ll need to use both hours and minutes:

fun earlier(tm1 :: TimeData, tm2 :: TimeData) -> Boolean:
  (tm1.hour < tm2.hour) or
  ((tm1.hour == tm2.hour) and (tm1.minute < tm2.minute))
where:
  earlier(time(0, 0), time(0, 1)) is true
  earlier(time(0, 1), time(1, 0)) is true
  earlier(time(1, 3), time(1, 2)) is false
  earlier(time(1, 0), time(0, 3)) is false
end