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