https://wiki.haskell.org/api.php?action=feedcontributions&user=Roconnor&feedformat=atomHaskellWiki - User contributions [en]2021-04-19T18:37:22ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Time&diff=57067Time2013-11-07T13:32:18Z<p>Roconnor: </p>
<hr />
<div>= Data Types for Measuring Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversalTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second", meaning the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> is the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
= Data Types for Denoting Time =<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
== Day ==<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> from the <tt>timezone-series</tt> packages will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56477Time2013-07-29T14:04:28Z<p>Roconnor: /* UTCTime */</p>
<hr />
<div>= Data Types for Measuring Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversalTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second", meaning the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> is the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
= Data Types for Denoting Time =<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
== Day ==<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> from the <tt>timezone-series</tt> packages will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56476Time2013-07-29T13:58:13Z<p>Roconnor: </p>
<hr />
<div>= Data Types for Measuring Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversalTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> is the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
= Data Types for Denoting Time =<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
== Day ==<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> from the <tt>timezone-series</tt> packages will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56475Time2013-07-29T13:56:09Z<p>Roconnor: /* NominalDiffTime */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversalTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> is the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> from the <tt>timezone-series</tt> packages will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56473Time2013-07-27T23:20:07Z<p>Roconnor: /* getTimeZone */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> from the <tt>timezone-series</tt> packages will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56472Time2013-07-27T23:19:18Z<p>Roconnor: /* Time */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time package by Ashley Yakeley. There are several similar but different concepts associated with time and the time package keeps these different concepts separated by different data types with appropriate transformations between them to help keep your logic sound. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what temporal concepts they represent. This will help make sure you are using the right data type for the right task. The first few data types in this guide are not widely used in practice, but it is important to understand their associated concepts before moving onto the more complex, widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is a data type is type for denoting when an event occurs. AbsoluteTime is a uniform time scale that simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future or past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>DiffTime</tt> is appropriate in situations where precision time differences are required; however <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of days (each day consisting of between 86399-86401 seconds) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days in the future will have a leap second. A leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds of years ago can be referenced with moderate precision because we may know approximately when during a particular day they occurred, even though we do not know the <tt>AbsoluteTime</tt> that they occurred (because we do not know the detailed historical changes in the rotation rate of the Earth). Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt> with a leap second table. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt>.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt>s if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to a high degree of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issues, the <tt>Day</tt> type does not necessarily refer to any specific 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However, it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regularly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting between common year-month-day-hour-minute-second human time format and absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredictable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time package that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.<br />
<br />
There is no functionality in the time package that will convert from a local regional time to <tt>UTCTime</tt>, owing to the fact that the same local regional time may refer to multiple different <tt>UTCTime</tt> due to daylight savings times. <tt>localTimeToUTC'</tt> will do this conversion given a <tt>TimeZoneSeries</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56471Time2013-07-27T22:23:27Z<p>Roconnor: </p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frustrated with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10<sup>-12</sup> seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most appropriate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rotation means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion utilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occurring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occurred, even though we won't know the <tt>AbsoluteTime</tt> that they occurred. Events occurring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown is often not a problem.<br />
<br />
The major disadvantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occurred between two <tt>UTCTime</tt> if no leap seconds had occurred between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precession. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would normally want said event to occur at the same time of day, or same minute of the hour, regardless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurrences of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usually tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of referring to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unusual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second up to a precession of 10-12. The seconds could go up to 61 in order to accommodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
<tt>LocalTime</tt> is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with <tt>LocalTime</tt> is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use <tt>LocalTime</tt>s to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancillary data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offset from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56470Time2013-07-27T21:41:10Z<p>Roconnor: /* Absolute Time */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== AbsoluteTime ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56469Time2013-07-27T21:31:48Z<p>Roconnor: /* NominalDiffTime */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== Absolute Time ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime</tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <tt>NominalDiffTime</tt> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56468Time2013-07-27T21:30:25Z<p>Roconnor: /* UTCTime */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== Absolute Time ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime</tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime</tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime<tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <code>NominalDiffTime<code> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56467Time2013-07-27T21:29:14Z<p>Roconnor: /* UniversalTime */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== Absolute Time ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime</tt> and <tt>AbsoluteTime</tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime<tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime<tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime<tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <code>NominalDiffTime<code> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56466Time2013-07-27T21:28:28Z<p>Roconnor: /* DiffTime */</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== Absolute Time ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime</tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime<tt> and <tt>AbsoluteTime<tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime<tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime<tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime<tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <code>NominalDiffTime<code> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Time&diff=56465Time2013-07-27T21:20:44Z<p>Roconnor: Initial Copy</p>
<hr />
<div>= Time =<br />
<br />
The canonical time library for Haskell is the time library by Ashley Yakeley. There are several similar but different concepts associated with time and the time library keys these different concepts separated by different data types with appropriate transformations between them to keep your logic safe. However, if you are trying to use the wrong data type for the wrong task, you may find yourself frusterted with the time library.<br />
<br />
To help avoid frustration, this guide will describe the various data types available in the time library and what concepts they represent in order help make sure you are using the right data type for the right task. The first few data types of this guide are not widely used in practice, but it is important to understand their conceptual uses before moving onto the more complex, but widely used, data types. <br />
<br />
== Absolute Time ==<br />
<br />
<tt>AbsoluteTime</tt> is found in the <tt>Data.Time.Clock.TAI</tt> module. This data type is the most appropriate type for denoting when an event occurs. AbsoluteTime simply counts the number of seconds since the TAI epoch. There are no leap seconds or timezones to worry about. You can compare two <tt>AbsoluteTime</tt>s directly to determine which one came first. You can reference time as far into the future and past as you like to within a resolution of 10^-12 seconds.<br />
<br />
Although <tt>AbsoluteTime</tt> is most approprate for many tasks, it is rarely used in applications and you will likely never use this data type. Unless you are a particularly pioneering person, you will probably want to use <tt>UTCTime</tt> which is more widely used in practice.<br />
<br />
== DiffTime ==<br />
<br />
<tt>DiffTime</tt> is used to represent an absolute duration of time measured in seconds. Subtracting two <tt>AbsoluteTime</tt>s with <tt>diffAbsoluteTime<tt> will produce a <tt>DiffTime</tt> and you can add a <tt>DiffTime</tt> to an <tt>AbsoluteTime</tt> to produce an offset <tt>AbsoluteTime</tt>.<br />
<br />
<tt>DiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>DiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real<tt> so <tt>round</tt> and <tt>realToFrac<tt> can operate on it.<br />
<br />
Although <tt>DiffTime</tt> may be appropriate in some situations where precision differences are required, <tt>NominalDiffTime</tt> is more often used in practice.<br />
<br />
== UniversalTime ==<br />
<br />
The problem with <tt>AbsoluteTime</tt> is that Earth's rotation rate is not constant. Over the long term, solar noon would drift over time. <tt>UniversalTime</tt> measures time by counting the number of "solar" rotations of the earth, including fractions of a rotation, of the earth since the MJD (Modifed Julian Date) epoch.<br />
<br />
The variations in the Earth's rototion means that a difference in <tt>UniversialTime</tt> does not correspond to any particular amount of time. Your computer's hardware cannot track <tt>UniversalTime</tt> since it can only measure absolute durations. Converting between <tt>UniversalTime<tt> and <tt>AbsoluteTime<tt> would require a database build upon astronomical observations. No such conversion untilities are provided.<br />
<br />
<tt>UniversalTime</tt> is almost never used in practice.<br />
<br />
== UTCTime ==<br />
<br />
<tt>UTCTime<tt> measures "Coordinated Universal Time". One second of <tt>UTCTime</tt> is a constant amount of time equal to one second of <tt>AbsoluteTime</tt>. However, in order to keep "coordinated" with Universal Time, the number of seconds per day varies. Most days have 86400 seconds; however, on occasion a day will have a "leap second" mean the day will consist of 86399 or 86401 seconds. <tt>UTCTime<tt> counts the number of integers days (rotations of the earth) since the MJD epoch plus an absolute time difference up to the number of seconds that occur in that day.<br />
<br />
It is unpredictable which days will have a leap second and a leap second table is needed to convert between <tt>AbsoluteTime</tt> and <tt>UTCTime</tt>. This conversion can only be done reliably within recent history.<br />
<br />
<tt>UTCTime</tt> is the most popular way of referencing events in absolute time. Events occuring hundreds or years ago can be referenced with moderate precision because we may know when during a particular day they occured, even though we won't know the <tt>AbsoluteTime</tt> that they occured. Events occuring in the recent past can be converted to <tt>AbsoluteTime</tt>. Future events are usually set relatative to the day in which they are to occur, so the fact that the absolute time that they will occur at (that is exact the number seconds into the future that they will occur) is unknown often is not a problem.<br />
<br />
The major disavantage with <tt>UTCTime</tt> is that one cannot compute the absolute difference between two <tt>UTCTime</tt>s without first converting them to <tt>AbsoluteTime</tt>, and that requires an accurate leap second tables. To circumvent this issue, one uses <tt>NominalDiffTime</tt> instead.<br />
<br />
== NominalDiffTime ==<br />
<br />
The <tt>diffUTCTime<tt> function computes a <tt>NominalDiffTime</tt> between two <tt>UTCTimes</tt> which is the number of seconds that would have occured between two <tt>UTCTime</tt> if no leap seconds had occured between the two events. Therefore the <tt>diffUTCTime</tt> is not suitable for measuring the absolute time between two events to within a second's worth of precssion. However a <tt>NominalDiffTime</tt> is often suitable for advancing an event by a week, a day, or an hour, since one would nomially want said event to occur at the same time of day, or same minute of the hour, regarless of whether or not a leap second happens to be inserted in that duration.<br />
<br />
<tt>NominalDiffTime</tt> is a member of the <tt>Num</tt> and <tt>Fractional</tt>, so can be generated by <tt>fromIntegral</tt> and <tt>realToFrac</tt>. <tt>NominalDiffTime</tt> is also a member of <tt>RealFrac</tt> and <tt>Real</tt> so <tt>round</tt> and <tt>realToFrac</tt> can operate on it.<br />
<br />
<tt>NominialDiffTime</tt> is regularly used. In fact, <tt>POSIXTime</tt> the <code>NominalDiffTime<code> since the UNIX epoch of Jan 1st, 1970, UTC.<br />
<br />
== Day ==<br />
<br />
So far our data have denoted occurances of events by counting the number of days, or the number of seconds since some fixed reference epoch. However we usally tell time by using years, months, day of month, hours, minutes and seconds. The remain data types will assist with this more usual approach to telling time.<br />
<br />
The <tt>Day</tt> data type is an abstract way of refering to a calender date. Due to time zone issue, the <tt>Day</tt> does not necessarily refer to any particular 1-day long absolute time period.<br />
<br />
The standard calender used to reference a date is the Gregorian calendar. The <tt>toGregorian</tt> and <tt>fromGregorian</tt> functions will construct and deconstruct a <tt>Day</tt> from the usual year-month-day format. There are other calendars, such as the Julian calendar, which are only used in unsual situations.<br />
<br />
== TimeOfDay ==<br />
<br />
<tt>TimeOfDay</tt> represents "wall-clock" time. It consists of an hour of the day, a minute of the hour, and a second of the minute, including fractions of a second upto a precession of 10-12. The seconds could go upto 61 in order to accomodate leap seconds.<br />
<br />
== LocalTime ==<br />
<br />
A <tt>Day</tt> with a <tt>TimeOfDay</tt> forms a <tt>LocalTime</tt>. This is contains the data that we normally denote time with: a year, month, day, hour, minute, and second. However it does not denote an absolute time because it contains no time zone information.<br />
<br />
LocalTime is used represent date and time for printing and parsing; however it should be avoided for computation. The biggest problem with LocalTime is that, due to daylight savings time, regualarly the same time of day is repeated twice a day. This means you cannot even use LocalTimes to reliably determine the relative order of events.<br />
<br />
== TimeZone ==<br />
<br />
Somewhat confusingly named, a <tt>TimeZone</tt> represents an offset from UTC measured in minutes. It also contains ancilery data such as the timezone name and whether or not it is intended to be used for summer time only. Eastern Standard Time (EST) or Pacific Daylight Time (PDT) are examples of timezone that could be represented by a <tt>TimeZone</tt> value. <br />
<br />
It does not represent the time zone of a region, such as Eastern Time, because regions often vary their offsets from UTC depending on the time of year.<br />
<br />
The <tt>utc</tt> value is the value of the <tt>TimeZone</tt> with no offest from UTC.<br />
<br />
== ZonedTime == <br />
<br />
A <tt>ZonedTime</tt> is a <tt>LocalTime</tt> together with a <tt>TimeZone</tt>. This does refer to a specific event in absolute time and can be converted to a <tt>UTCTime</tt> with the <tt>zoneTimeToUTC</tt> function, and could be further converted into a <tt>AbsoluteTime</tt> if one has a leap second table.<br />
<br />
There are, of course, many different <tt>ZonedTime</tt> values corresponding to the same absolute, <tt>UTCTime</tt>. Given a <tt>TimeZone</tt> one can create a <tt>ZonedTime</tt> with that <tt>TimeZone</tt> by using the <tt>utcToZonedTime</tt> function.<br />
<br />
<tt>ZoneTime</tt> is a common stop when converting common year-month-day-hour-minute-second human time format and an absolute <tt>UTCTime</tt> time.<br />
<br />
== TimeZoneSeries ==<br />
<br />
Almost nothing in the time library deals with regional time zones such as "Eastern Time" or "Pacific time" For that we need to reach out to the timezone-series and timezone-olson packages. The difficulty with regional time zones is, like leap seconds, that they are unpredicable and subject to be changed. <br />
<br />
A <tt>TimeZoneSeries</tt> is a series of <tt>TimeZone</tt>s, that is offsets from UTC, along with the absolute times where those <tt>TimeZone</tt>s are in effect. This is a suitable structure for defining a regional time zone. The functions in the timezone-olson package will allow you to create a <tt>TimeZoneSeries</tt> from an Olson time zone database file.<br />
<br />
== getTimeZone ==<br />
<br />
There there is one set of functions in the time library that does deal with regional time zones. The <tt>getTimeZone</tt> function will compute the timezone for a given, absolute, <tt>UTCTime</tt>, but only the local region as set by the <tt>TZ</tt> environment variable. The <tt>getCurrentTimeZone</tt>, <tt>getZonedTime</tt>, and <tt>utcToLocalZonedTime</tt> are functions derived from <tt>getTimeZone</tt>.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=44084Multiplate2012-01-20T02:01:26Z<p>Roconnor: Applicative Functors need to be imported.</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
> import Control.Applicative<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate child = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr child e1 <*> expr child e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr child e1 <*> expr child e2<br />
> buildExpr (Let d e) = Let <$> decl child d <*> expr child e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr child e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl child d1 <*> decl child d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre><br />
<br />
== Alternative Plates ==<br />
<br />
Multiplate does not have to be used in the above way. Any structure can be made an instance of <code>Multiplate</code> as long as the following two Multiplate laws are satisfied:<br />
<br />
<OL><br />
<LI><code>multiplate purePlate = purePlate</code><br />
<LI><code>multiplate (composePlate p1 p2) = composePlate (multiplate p1) (multiplate p2)</code><br />
</OL><br />
<br />
For example, Sjoerd Visscher gives [https://gist.github.com/707890 an example] of a plate where each constructor of each data type has its own field in a record structure.<br />
<br />
== Links ==<br />
<br />
[http://hackage.haskell.org/package/multiplate Multiplate on Hackage]</div>Roconnorhttps://wiki.haskell.org/index.php?title=Zygohistomorphic_prepromorphisms&diff=38851Zygohistomorphic prepromorphisms2011-02-20T21:03:16Z<p>Roconnor: </p>
<hr />
<div>Used when you really need both semi-mutual recursion and history and to repeatedly apply a natural transformation as you get deeper into the functor. Zygo implements semi-mutual recursion like a zygomorphism. Para gives you access to your result Ã la paramorphism.<br />
<br />
<pre><br />
import Control.Morphism.Zygo<br />
import Control.Morphism.Prepro<br />
import Control.Morphism.Histo<br />
import Control.Functor.Algebra<br />
import Control.Functor.Extras<br />
<br />
zygoHistoPrepro <br />
:: (Unfoldable t, Foldable t) <br />
=> (Base t b -> b) <br />
-> (forall c. Base t c -> Base t c) <br />
-> (Base t (EnvT b (Stream (Base t)) a) -> a) <br />
-> t<br />
-> a<br />
zygoHistoPrepro f g t = gprepro (distZygoT f distHisto) g t<br />
-- unless you want a generalized zygomorphism.<br />
</pre></div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37718Multiplate2010-12-04T00:59:46Z<p>Roconnor: spelling</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate child = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr child e1 <*> expr child e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr child e1 <*> expr child e2<br />
> buildExpr (Let d e) = Let <$> decl child d <*> expr child e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr child e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl child d1 <*> decl child d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre><br />
<br />
== Alternative Plates ==<br />
<br />
Multiplate does not have to be used in the above way. Any structure can be made an instance of <code>Multiplate</code> as long as the following two Multiplate laws are satisfied:<br />
<br />
<OL><br />
<LI><code>multiplate purePlate = purePlate</code><br />
<LI><code>multiplate (composePlate p1 p2) = composePlate (multiplate p1) (multiplate p2)</code><br />
</OL><br />
<br />
For example, sjoerd_visscher gives [https://gist.github.com/707890 an example] of a plate where each constructor of each data type has its own field in a record structure.<br />
<br />
== Links ==<br />
<br />
[http://hackage.haskell.org/package/multiplate Multiplate on Hackage]</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37717Multiplate2010-12-04T00:59:23Z<p>Roconnor: spelling</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate child = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr child e1 <*> expr child e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr child e1 <*> expr child e2<br />
> buildExpr (Let d e) = Let <$> decl child d <*> expr child e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr child e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl child d1 <*> decl child d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre><br />
<br />
== Alternative Plates ==<br />
<br />
Multiplate does not have to be used in the above way. Any structure can be made an instance of <code>Multiplate</code> as long as the following two Multiplate laws are satisfied:<br />
<br />
<OL><br />
<LI><code>multiplate purePlate = purePlate</code><br />
<LI><code>multiplate (composePlate p1 p2) = composePlate (multiplate p1) (multiplate p2)</code><br />
</OL><br />
<br />
For example, sjoerd_visscher gives [https://gist.github.com/707890 an example] of a plate where each constructor of each data type has it's own field in a record structure.<br />
<br />
== Links ==<br />
<br />
[http://hackage.haskell.org/package/multiplate Multiplate on Hackage]</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37716Multiplate2010-12-04T00:57:51Z<p>Roconnor: Alternative Plates</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate child = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr child e1 <*> expr child e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr child e1 <*> expr child e2<br />
> buildExpr (Let d e) = Let <$> decl child d <*> expr child e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr child e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl child d1 <*> decl child d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre><br />
<br />
== Alternative Plates ==<br />
<br />
Multiplate does not have to be used in the above way. Any structure can be made an instance of <code>Multiplate</code> as long as the following two Multiplate laws are satified:<br />
<br />
<OL><br />
<LI><code>multiplate purePlate = purePlate</code><br />
<LI><code>multiplate (composePlate p1 p2) = composePlate (multiplate p1) (multiplate p2)</code><br />
</OL><br />
<br />
For example, sjoerd_visscher gives [https://gist.github.com/707890 an example] of a plate where each constructor of each data type has it's own field in a record structure.<br />
<br />
== Links ==<br />
<br />
[http://hackage.haskell.org/package/multiplate Multiplate on Hackage]</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37529Multiplate2010-11-22T21:26:49Z<p>Roconnor: alpha conversion</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate child = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr child e1 <*> expr child e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr child e1 <*> expr child e2<br />
> buildExpr (Let d e) = Let <$> decl child d <*> expr child e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr child e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl child d1 <*> decl child d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre></div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37512Multiplate2010-11-20T03:15:59Z<p>Roconnor: </p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by an applicative functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate plate = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Let d e) = Let <$> decl plate d <*> expr plate e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr plate e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl plate d1 <*> decl plate d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre></div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37511Multiplate2010-11-20T02:58:42Z<p>Roconnor: </p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
> import Data.Functor.Identity<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by a functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate plate = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Let d e) = Let <$> decl plate d <*> expr plate e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr plate e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl plate d1 <*> decl plate d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Suppose we want to recursively evaluate constant expressions in the language.<br />
We can use <code>mapFamily</code> for this.<br />
We define a <code>Plate Identity</code> for the functionality we care about.<br />
<br />
<pre><br />
doConstFold :: Plate Identity<br />
doConstFold = purePlate { expr = exprConst }<br />
where<br />
expr (Add (Con x) (Con y)) = return (Con (x + y))<br />
expr (Mul (Con x) (Con y)) = return (Con (x * y))<br />
expr x = pure x<br />
</pre><br />
<br />
Now we can can build a plate that will repeatedly apply this transformation from bottom up.<br />
<br />
<pre><br />
constFoldPlate = mapFamily doConstFold<br />
</pre><br />
<br />
Let's build an declaration to test.<br />
<br />
<pre><br />
d1 :: Decl<br />
d1 = "x" := (Add (Mul (Con 42) (Con 68)) (Con 7))<br />
</pre><br />
<br />
We can project out the function for <code>Decl</code>'s from our plate apply it to <code>d1</code> and then unwrap the <code>Identity</code> wrapper. Again, there is a little helper function, called <code>traverseFor</code>, that will upgrade of projection function to remove the <code>Identity</code> wrapper for us.<br />
<br />
<pre><br />
>>> traverseFor decl constFoldPlate d1<br />
<br />
"x" := Con 2863<br />
</pre></div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37509Multiplate2010-11-19T22:35:00Z<p>Roconnor: Using monoid to sumerize data from structures</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example. We assume you have the transformers library installed.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
> import Data.Functor.Constant<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by a functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate plate = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Let d e) = Let <$> decl plate d <*> expr plate e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr plate e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl plate d1 <*> decl plate d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate.<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
=== Monoids ===<br />
<br />
Suppose we we want to get a list of all variables used in an expression. To do this we would use <code>preorderFold</code> with the list monoid. The first step is to build a <code>Plate</code> that handles the cases we care about. What we can do is use the default <code>purePlate</code> which does nothing, and modify it to handle the cases we care about.<br />
<br />
<pre><br />
getVariablesPlate :: Plate (Constant [Var])<br />
getVariablesPlate = purePlate { exprPlate = exprVars }<br />
where<br />
exprVars (EVar v) = Constant [v]<br />
exprVars x = pure x<br />
</pre><br />
<br />
This can be written alternatively using some list comprehension tricks<br />
<br />
<pre><br />
getVariablesPlate = purePlate {expr = \x -> Constant [s|EVar s <- [x]]}<br />
</pre><br />
<br />
Now we can can build a plate that will get variables from all subexpressions and concatenate them together into one big list<br />
<br />
<pre><br />
variablesPlate = preorderFold getVariablesPlate<br />
</pre><br />
<br />
In a real program we would either put <code>getVariablesPlate</code> into <code>variablesPlates</code>'s <code>where</code> clause or else simply inline<br />
the definition.<br />
<br />
<code>variablesPlate</code> is a record of functions that will give a list of variables for each type in our mutually recursive record. Say we have an <code>Expr</code> we want to apply this to.<br />
<br />
<pre><br />
e1 :: Expr<br />
e1 = Let ("x" := Con 42) (Add (EVar "x") (EVar "x"))<br />
</pre><br />
<br />
We can project out the function for <code>Expr</code>'s from our plate apply it to <code>e1</code> and then unwrap the <code>Constant</code> wrapper. There is a little helper function, called <code>foldFor</code>, that will upgrade of projection function to remove the <code>Constant</code> wrapper for us.<br />
<br />
<pre><br />
>>> foldFor expr variablesPlate e1<br />
<br />
["x","x"]<br />
</pre><br />
<br />
=== Traversing ===<br />
<br />
Coming Soon.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37508Multiplate2010-11-19T22:11:34Z<p>Roconnor: An example of how to make Multiplate instaces.</p>
<hr />
<div>== Making a Multiplate instance ==<br />
<br />
The easiest way to understand how to use Multiplate is to look at a simple example.<br />
<br />
<pre><br />
<br />
> import Data.Generics.Multiplate<br />
<br />
</pre><br />
<br />
Suppose you defined the follow set of mutually recursive data types for a simple language.<br />
<br />
<pre><br />
<br />
> data Expr = Con Int<br />
> | Add Expr Expr<br />
> | Mul Expr Expr<br />
> | EVar Var<br />
> | Let Decl Expr<br />
> deriving (Eq, Show)<br />
> <br />
> data Decl = Var := Expr<br />
> | Seq Decl Decl<br />
> deriving (Eq, Show)<br />
> <br />
> type Var = String<br />
<br />
</pre><br />
<br />
The first thing we are going to define is a 'plate' for this language.<br />
<br />
<pre><br />
<br />
> data Plate f = Plate<br />
> { expr :: Expr -> f Expr<br />
> , decl :: Decl -> f Decl<br />
> }<br />
<br />
</pre><br />
<br />
A plate is a record type that is parametrized by a functor <code>f</code>. There is one field for each type in the mutually recursive structure we want to write generic functions for. Each field has type <code>A -> f A</code> where <code>A</code> is one of the data types.<br />
<br />
To use the Multiplate library we have to make <code>Plate</code> and instance of the <code>Multiplate</code> class. The instance requires that we write two functions: <code>multiplate</code> and <code>mkPlate</code>. Let's define each of these functions in turn.<br />
<br />
<pre><br />
<br />
> instance Multiplate Plate where<br />
<br />
</pre><br />
<br />
We have to write one piece of boilerplate code for <code>multiplate</code>. However, once this is implemented, no further boilerplate code need be written.<br />
<code>multiplate</code> takes a <code>Plate</code> as a parameter. The idea is that for each expression in our language we will call this a function from this <code>Plate</code> parameter on the children of our expression and then combine the results.<br />
<br />
<pre><br />
<br />
> multiplate plate = Plate buildExpr buildDecl<br />
> where<br />
> buildExpr (Add e1 e2) = Add <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Mul e1 e2) = Mul <$> expr plate e1 <*> expr plate e2<br />
> buildExpr (Let d e) = Let <$> decl plate d <*> expr plate e<br />
> buildExpr e = pure e<br />
> buildDecl (v := e) = (:=) <$> pure v <*> expr plate e<br />
> buildDecl (Seq d1 d2) = Seq <$> decl plate d1 <*> decl plate d2<br />
<br />
</pre><br />
<br />
Notice that when an expression has no children, as in the case of <code>v</code> in <code>v := e</code>, we simply use <code>pure v</code>.<br />
<code>pure</code> is used to handle the default case in <code>buildExpr</code>, also have no subexpressions.<br />
<br />
Next we have to define <code>mkPlate</code>. <code>mkPlate</code> is a function that builds a <code>Plate</code> given a generic builder function that produces values of type <code>a -> f a</code>. However these generic builder functions require a bit of help. The need to know what the projection function for the field that they are building is, so we pass that as a parameter to them.<br />
<br />
<pre><br />
<br />
> mkPlate build = Plate (build expr) (build decl)<br />
<br />
</pre><br />
<br />
That's it. Now we are ready to use out generic library to process our mutually recursive data structure without using any more boilerplate<br />
<br />
== Generic Programing with Multiplate ==<br />
<br />
Coming Soon.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Multiplate&diff=37479Multiplate2010-11-16T21:07:28Z<p>Roconnor: Dibbs on this page.</p>
<hr />
<div>Coming Soon.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Yhc/Building&diff=37325Yhc/Building2010-10-22T16:33:25Z<p>Roconnor: I found this other link more useful.</p>
<hr />
<div>{{Yhc}}<br />
<br />
== Requirements ==<br />
<br />
You need a C compiler - both gcc and MS Visual C are known to be OK.<br />
<br />
You need [http://www.scons.org/ scons], which in turn requires [http://www.python.org/ Python] to be installed. We require Python 2.3 or later to be installed.<br />
<br />
The process of building Yhc requires [http://haskell.org/ghc/ ghc-6.4] or later and [http://darcs.net/ darcs].<br />
<br />
== Getting the code ==<br />
<br />
The source code is stored in a [http://www.darcs.net/ darcs] repo, to get the code do:<br />
<br />
darcs get --partial http://darcs.haskell.org/york-compiler98/<br />
<br />
{- maybe darcs get --partial http://www.cs.york.ac.uk/fp/darcs/yhc/ is more recent? -}<br />
<br />
There is a buildbot script that runs on every change, the results of which are available [http://www.indiegigs.co.uk:8010/ here]. If the build is busted, hopefully the developers will fix it soon. If your build is busted, but the buildbot succeeds, [[Yhc/Buildbot| consider adding your machine as a buildbot slave]] - then it will never get broken again.<br />
<br />
== Building ==<br />
<br />
To build yhc simply type 'scons' into a console Window. This should automatically detect your build environment and place the Yhc binaries into inst/<br />
<br />
To build parts of Yhc separately the following commands can be used:<br />
* scons configure - Just configure.<br />
* scons build - Don't update dependencies, just build.<br />
* scons build yhi - Only build the interpretor.<br />
* scons build yhc - Only build the compiler.<br />
* scons build library - Only build the libraries.<br />
<br />
Other commands available are:<br />
* scons clean - Remove temporary files.<br />
* scons fullclean - Completely wipe everything created by the build process.<br />
* scons depends - Download or update the dependencies<br />
* scons help - Show a help message<br />
<br />
To test Yhc has been build correctly type 'scons test'.<br />
<br />
Please report any problems you have to the mailing list.<br />
<br />
<small><br />
Please also note that these steps do not currently build the Javascript backend; please refer to [[Yhc/Javascript/Users_guide|Yhc/Javascript/Users guide]] for information how to build '''ycr2js'''.<br />
</small><br />
<br />
== Scons options ==<br />
<br />
Options can be given to scons by either passing the flags on the command line 'core=1' or by creating a file called options.txt in the root Yhc directory. The available flags are:<br />
<br />
* core=1 (default=1) - generate Yhc Core files for each file in the libraries<br />
* arch=X86 (default=calculated) - override the arch, useful for building 32 bit version on a 64 bit kernel.<br />
* type=release/debug/normal (default=normal) - enables debug information or optimisation<br />
* threads=0 (default=1, except on ppc where the default is 0) - disables threading<br />
<br />
== If something goes wrong ==<br />
<br />
If the build fails for any reason, try the following steps:<br />
<br />
; scons fullclean<br />
; scons depends<br />
<br />
Then try building again.<br />
<br />
== Build options ==<br />
<br />
"scons help" shows some options for the build process.<br />
<br />
To build with additional library/header paths, e.g. for GMP:<br />
<br />
CCFLAGS="-I/.../include" LIBPATH=/.../lib scons</div>Roconnorhttps://wiki.haskell.org/index.php?title=Orphan_instance&diff=36811Orphan instance2010-09-21T13:35:19Z<p>Roconnor: </p>
<hr />
<div>Warning: this page is <br />
<br />
== Question ==<br />
<br />
What is an Orphan instance and why is it bad?<br />
<br />
== Answer ==<br />
<br />
An orphan instance is a [[type class instance]] for class C and type T which is neither defined in the module where C is defined nor in the module where T is defined.<br />
<br />
Type class instances are special in that they don't have a name and cannot be imported explicitly. This also means, that they can not be excluded explicitly. All instances defined in a module A are imported automatically when importing A. This applies recursively to all modules imported by A.<br />
<br />
Say you want to make use of a type class instance in your module, then you must import both the class and the type directly, or you must import modules which itself import at some point the class and at some other point the type. If there is a non-orphan instance, you automatically get the instance imported. This way the compiler can restrict the set of modules to look for an instance if you want to apply it. So the problem is partially an efficiency problem, but this is not all.<br />
<br />
Say you want to define an alternative instance to an existing instance. This is a bad thing, since if two instances for the same class/type pair are in scope, then you cannot describe in Haskell 98 which instance to use. If you want to use multiple instances for the same class/type, you have to ensure, that they are never imported together in a module somewhen. It is almost impossible to assert that, or put differently, it would reduce the composability of libraries considerably.<br />
<br />
The <hask>Monad</hask> instance of <hask>Either</hask> is a good example.<br />
It is not defined where <hask>Either</hask> is defined, thus all of its <hask>Monad</hask> instances must be orphan.<br />
Instead it is defined both in <hask>Control.Monad.Error</hask> of the [[Monad Transformer Library]]<br />
and in <hask>Control.Monad.Trans.Error</hask> of its leightweight cousin the 'transformers' package.<br />
Since some packages use MTL and others 'transformers' it becomes difficult to use that instance at all,<br />
although both instances are equivalent!<br />
Practical advice:<br />
The [[Exception|explicit-exception]] package with its <hask>Exceptional</hask> might be a better choice to use since it avoids the current problem with orphan Monad instances of <hask>Either</hask>.<br />
<br />
Actually, non-orphan instances can avoid definition of [[multiple instances]]. For defining an instance you have to import the class and the type and then you will automatically have the according non-orphan instances imported, too. If you want to define a new instance then the compiler will reject it immediately.<br />
<br />
<br />
A last advice:<br />
If you encounter a missing instance for a class or a type of a package,<br />
resist to define your own orphan instance, because it will likely collide with such instances of other packages,<br />
or it will collide with new instances added in later versions of that package.<br />
Instead ask the package author to add your instance.<br />
Sometimes it turns out that the instance was not included for the good reason,<br />
that there is more than one reasonable instance definition.<br />
If your instance cannot be included, follow the advices in the article about [[multiple instances]].<br />
<br />
<br />
== See also ==<br />
<br />
* [[Multiple instances]]<br />
* Libraries mailing list on [http://www.haskell.org/pipermail/libraries/2008-August/010399.html Orphan instances can be good]<br />
* [http://modula3.elegosoft.com/pm3/pkg/modula3/src/discussion/partialRev.html Partial Revelation feature] of Modula-3 which causes similar problems like Haskell's type class instances<br />
<br />
[[Category:FAQ]]<br />
[[Category:Style]]</div>Roconnorhttps://wiki.haskell.org/index.php?title=IO_Semantics&diff=34693IO Semantics2010-05-08T21:57:45Z<p>Roconnor: </p>
<hr />
<div>[[Category:Theoretical_foundations]]<br />
== Semantics of IO: A Free Approach ==<br />
<br />
The following is inspired by [http://luqui.org/blog/archives/2008/03/29/io-monad-the-continuation-presentation/ Luke Palmer's post]. This only describes one possible semantics of <hask>IO a</hask>; your actually implementation may vary.<br />
<br />
The idea is to define <hask>IO</hask> as<br />
<haskell><br />
data IO a = Done a<br />
| PutChar Char (IO a)<br />
| GetChar (Char -> IO a)<br />
</haskell><br />
<br />
For simplicity this an example of <hask>IO</hask> that only gives semantics for teletype IO.<br />
<br />
Think of <hask>IO a</hask> as a tree whose leaves are <hask>Done a</hask> that holds the result of the program. <hask>PutChar</hask> is a node that has one child tree and the node holds one character of data. <hask>GetChar</hask> is a node that has many children; it has one child for every <hask>Char</hask>, but <hask>GetChar</hask> holds no data itself.<br />
<br />
This tree contains all the information needed to execute teletype interactions.<br />
One interprets (or executes) an <hask>IO a</hask> by tracing a route from root of the tree to a leaf.<br />
<br />
If a <hask>PutChar</hask> node is encountered, the character data contained at that node is output to the terminal and then its subtree is executed. It is at this point that Haskell code evaluated in order to determine what character should be displayed before continuing. If a <hask>GetChar</hask> node is encountered, a character is read from the terminal (blocking if necessary) and the subtree corresponding to the character received is executed. If <hask>Done</hask> is encountered the program ends. <hask>Done</hask> holds the result of the computation, but in the case of <hask>main :: IO ()</hask> the data is of type <hask>()</hask> and thus contains no information and is ignored.<br />
<br />
This execution is not done anywhere in a haskell program, rather it is done by the run-time system.<br />
<br />
The monadic operations are defined as follows:<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return x = Done x<br />
<br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
Done x >>= f = f x<br />
PutChar c x >>= f = PutChar c (x >>= f)<br />
GetChar g >>= f = GetChar (\c -> g c >>= f)<br />
</haskell><br />
<br />
As you can see <hask>return</hask> is just another name for <hask>Done</hask>. The bind operation takes a tree <hask>x</hask> and a function <hask>f</hask> and replaces the <hask>Done</hask> nodes (the leaves) of <hask>x</hask> by a new tree produce by applying <hask>f</hask> to the data held in the <hask>Done</hask> nodes.<br />
<br />
The primitive IO commands are defined using these constructors.<br />
<haskell><br />
putChar :: Char -> IO ()<br />
putChar x = PutChar x (Done ())<br />
<br />
getChar :: IO Char<br />
getChar = GetChar (\c -> Done c)<br />
</haskell><br />
<br />
The function <hask>putChar</hask> builds a small <hask>IO ()</hask> tree that contains one <hask>PutChar</hask> node holding the character data followed by <hask>Done</hask>.<br />
<br />
The function <hask>getChar</hask> builds a short <hask>IO Char</hask> tree that begins with a <hask>GetChar</hask> that holds one <hask>Done</hask> node holding every character.<br />
<br />
Other teletype commands can be defined in terms of these primitives<br />
<haskell><br />
putStr :: String -> IO ()<br />
putStr = mapM_ putChar<br />
</haskell><br />
<br />
More generally speaking, <hask>IO a</hask> will represent the desired interaction with the operating system. For every system call there will be a corresponding constructor in <hask>IOTree</hask> of the form<br />
<haskell><br />
| SysCallName p1 p2 ... pn (r -> IO a)<br />
</haskell><br />
where <hask>p1</hask> ... <hask>pn</hask> are the parameters for the system call, and <hask>r</hask> is the result of the system call. (Thus <hask>PutChar</hask> and <hask>GetChar</hask> will not occur as constructors of <hask>IOTree</hask> if they don't correspond to system calls)</div>Roconnorhttps://wiki.haskell.org/index.php?title=IO_Semantics&diff=34692IO Semantics2010-05-08T21:49:14Z<p>Roconnor: Rewritten to remove continuations.</p>
<hr />
<div>[[Category:Theoretical_foundations]]<br />
== Semantics of IO: A Continuation Approach ==<br />
<br />
The following is inspired by [http://luqui.org/blog/archives/2008/03/29/io-monad-the-continuation-presentation/ Luke Palmer's post]. This only describes one possible semantics of <hask>IO a</hask>; your actually implementation may vary.<br />
<br />
The idea is to define <hask>IO</hask> as<br />
<haskell><br />
data IO a = Done a<br />
| PutChar Char (IO a)<br />
| GetChar (Char -> IO a)<br />
</haskell><br />
<br />
For simplicity this an example of <hask>IO</hask> that only gives semantics for teletype IO.<br />
<br />
Think of <hask>IO a</hask> as a tree whose leaves are <hask>Done a</hask> that holds the result of the program. <hask>PutChar</hask> is a node that has one child tree and the node holds one character of data. <hask>GetChar</hask> is a node that has many children; it has one child for every <hask>Char</hask>, but <hask>GetChar</hask> holds no data itself.<br />
<br />
This tree contains all the information needed to execute teletype interactions.<br />
One interprets (or executes) an <hask>IO a</hask> by tracing a route from root of the tree to a leaf.<br />
<br />
If a <hask>PutChar</hask> node is encountered, the character data contained at that node is output to the terminal and then its subtree is executed. It is at this point that Haskell code evaluated in order to determine what character should be displayed before continuing. If a <hask>GetChar</hask> node is encountered, a character is read from the terminal (blocking if necessary) and the subtree corresponding to the character received is executed. If <hask>Done</hask> is encountered the program ends. <hask>Done</hask> holds the result of the computation, but in the case of <hask>main :: IO ()</hask> the data is of type <hask>()</hask> and thus contains no information and is ignored.<br />
<br />
This execution is not done anywhere in a haskell program, rather it is done by the run-time system.<br />
<br />
The monadic operations are defined as follows:<br />
<br />
<haskell><br />
return :: a -> IO a<br />
return x = Done x<br />
<br />
(>>=) :: IO a -> (a -> IO b) -> IO b<br />
Done x >>= f = f x<br />
PutChar c x >>= f = PutChar c (x >>= f)<br />
GetChar g >>= f = GetChar (\c -> g c >>= f)<br />
</haskell><br />
<br />
As you can see <hask>return</hask> is just another name for <hask>Done</hask>. The bind operation takes a tree <hask>x</hask> and a function <hask>f</hask> and replaces the <hask>Done</hask> nodes (the leaves) of <hask>x</hask> by a new tree produce by applying <hask>f</hask> to the data held in the <hask>Done</hask> nodes.<br />
<br />
The primitive IO commands are defined using these constructors.<br />
<haskell><br />
putChar :: Char -> IO ()<br />
putChar x = PutChar x (Done ())<br />
<br />
getChar :: IO Char<br />
getChar = GetChar (\c -> Done c)<br />
</haskell><br />
<br />
The function <hask>putChar</hask> builds a small <hask>IO ()</hask> tree that contains one <hask>PutChar</hask> node holding the character data followed by <hask>Done</hask>.<br />
<br />
The function <hask>getChar</hask> builds a short <hask>IO Char</hask> tree that begins with a <hask>GetChar</hask> that holds one <hask>Done</hask> node holding every character.<br />
<br />
Other teletype commands can be defined in terms of these primitives<br />
<haskell><br />
putStr :: String -> IO ()<br />
putStr = mapM_ putChar<br />
</haskell><br />
<br />
More generally speaking, <hask>IO a</hask> will represent the desired interaction with the operating system. For every system call there will be a corresponding constructor in <hask>IOTree</hask> of the form<br />
<haskell><br />
| SysCallName p1 p2 ... pn (r -> IO a)<br />
</haskell><br />
where <hask>p1</hask> ... <hask>pn</hask> are the parameters for the system call, and <hask>r</hask> is the result of the system call. (Thus <hask>PutChar</hask> and <hask>GetChar</hask> will not occur as constructors of <hask>IOTree</hask> if they don't correspond to system calls)</div>Roconnorhttps://wiki.haskell.org/index.php?title=Talk:IO_Semantics&diff=33662Talk:IO Semantics2010-02-19T04:22:49Z<p>Roconnor: </p>
<hr />
<div>I don't understand in what sense this IO definition is a "semantics". [[User:Conal|Conal]] 04:49, 12 December 2008 (UTC)<br />
<br />
It provides a concrete definition of IO that can be compared for equality to know if two IO programs are equivalent or not. --[[User:Roconnor|Roconnor]] 03:54, 3 December 2009 (UTC)<br />
<br />
Maybe so. Thanks. For a semantics, I think I'd want a lot more equalities than the representation by itself provides, especially involving <hask>SysCallName</hask>.<br />
<br />
Also (raising a new question), I don't see this semantic model at all addressing concurrency, which is a huge semantic complicator for imperative computation. [[User:Conal|Conal]] 08:13, 3 December 2009 (UTC)<br />
<br />
You are correct that it doesn't. IOTree is essentailly a representation of (uniformly) continuous functions between streams of digits (aka 2^N --> 2^N) (see Peter Hancock's "eating"). I recall Bas Spitters suggesting that making this even more higher order in some way that I forget could be used to capture concurrency, but I never understood the details and haven't thought about it for a few years. I should look at my email archives.<br />
--[[User:Roconnor|Roconnor]] 04:18, 19 February 2010 (UTC)</div>Roconnorhttps://wiki.haskell.org/index.php?title=Talk:IO_Semantics&diff=33661Talk:IO Semantics2010-02-19T04:18:50Z<p>Roconnor: </p>
<hr />
<div>I don't understand in what sense this IO definition is a "semantics". [[User:Conal|Conal]] 04:49, 12 December 2008 (UTC)<br />
<br />
It provides a concrete definition of IO that can be compared for equality to know if two IO programs are equivalent or not. --[[User:Roconnor|Roconnor]] 03:54, 3 December 2009 (UTC)<br />
<br />
Maybe so. Thanks. For a semantics, I think I'd want a lot more equalities than the representation by itself provides, especially involving <hask>SysCallName</hask>.<br />
<br />
Also (raising a new question), I don't see this semantic model at all addressing concurrency, which is a huge semantic complicator for imperative computation. [[User:Conal|Conal]] 08:13, 3 December 2009 (UTC)<br />
<br />
You are correct that it doesn't. IOTree is essentailly a representation of (uniformly) continuous functions between streams of digits (aka 2^N --> 2^N). I recall Bas Spitters suggesting that making this even more higher order in some way that I forget could be used to capture concurrency, but I never understood the details and haven't thought about it for a few years. I should look at my email archives.<br />
--[[User:Roconnor|Roconnor]] 04:18, 19 February 2010 (UTC)</div>Roconnorhttps://wiki.haskell.org/index.php?title=Talk:IO_Semantics&diff=32083Talk:IO Semantics2009-12-03T03:54:41Z<p>Roconnor: </p>
<hr />
<div>I don't understand in what sense this IO definition is a "semantics". [[User:Conal|Conal]] 04:49, 12 December 2008 (UTC)<br />
<br />
It provides a concrete definition of IO that can be compared for equality to know if two IO programs are equivalent or not. --[[User:Roconnor|Roconnor]] 03:54, 3 December 2009 (UTC)</div>Roconnorhttps://wiki.haskell.org/index.php?title=Talk:Package_versioning_policy&diff=29809Talk:Package versioning policy2009-08-29T20:28:25Z<p>Roconnor: alternative specification of versioning policy</p>
<hr />
<div>How about describing the semantics of versions in the following way?<br />
<br />
1. If none of the module interfaces of your package have changed, the A.B.C prefix can remain the same.<br />
<br />
2. If a user of the package only used qualified imports and/or imports a specified list of functions would imply that they could use your new package version, then the A.B prefix can remain the same.<br />
<br />
3. Otherwise, the A.B prefix must be incremented.<br />
<br />
Is this equivalent to the versioning policy?<br />
<br />
--[[User:Roconnor|Roconnor]] 20:28, 29 August 2009 (UTC)</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29807Colour2009-08-29T19:35:19Z<p>Roconnor: black is now exported from Data.Colour</p>
<hr />
<div>[[Category:Libraries]]<br />
<br />
This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out-of-gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out-of-gamut colour could result.<br />
<br />
Colour intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out-of-gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours (for example, when writing a ray-tracer), you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out-of-gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour over black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` black)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=29806How to write a Haskell program2009-08-29T19:21:57Z<p>Roconnor: corrected syntax for build depends</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base >= 3 && < 5<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Roconnorhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=29805How to write a Haskell program2009-08-29T19:14:53Z<p>Roconnor: constraints for libs too</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && base < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base >= 3 && base < 5<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Roconnorhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=29804How to write a Haskell program2009-08-29T19:12:27Z<p>Roconnor: base >= 3 because not every major distro has GHC 6.10</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && base < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Roconnorhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=29803How to write a Haskell program2009-08-29T19:10:33Z<p>Roconnor: Adding constraints for base.</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 4 && base < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29078Colour2009-07-13T14:32:26Z<p>Roconnor: ray-tracer example</p>
<hr />
<div>[[Category:Libraries]]<br />
<br />
This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out-of-gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out-of-gamut colour could result.<br />
<br />
Colour intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out-of-gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours (for example, when writing a ray-tracer), you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out-of-gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour over black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29063Colour2009-07-10T17:22:06Z<p>Roconnor: </p>
<hr />
<div>[[Category:Libraries]]<br />
<br />
This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour over black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29062Colour2009-07-10T17:02:19Z<p>Roconnor: category</p>
<hr />
<div>[[Category:Libraries]]<br />
<br />
This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour over black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29060Colour2009-07-10T15:58:40Z<p>Roconnor: </p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour over black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29058Colour2009-07-10T14:59:19Z<p>Roconnor: spelling</p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safely "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29057Colour2009-07-10T14:56:43Z<p>Roconnor: corrections</p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will create such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels will be clamped to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>.<br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29051Colour2009-07-10T05:59:31Z<p>Roconnor: </p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut by making colours too intense. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29050Colour2009-07-10T05:45:53Z<p>Roconnor: </p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask>.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29049Colour2009-07-10T05:45:21Z<p>Roconnor: module for curryRGB and uncurryRGB</p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples. These functions can be found in <hask>Data.Colour.RGBSpace</hask><br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29048Colour2009-07-10T05:42:52Z<p>Roconnor: </p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque <hask>AlphaColour</hask>s are created from <hask>Colour</hask>s using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29047Colour2009-07-10T05:42:09Z<p>Roconnor: alphaColourConvert</p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>. You can use <hask>alphaColourConvert</hask> to change the internal representation type of a semi-transparent colour.<br />
<br />
Opaque AlphaColours are created from Colours using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29046Colour2009-07-10T05:38:23Z<p>Roconnor: type annotation for pureColour</p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>.<br />
<br />
Opaque AlphaColours are created from Colours using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour :: AlphaColour a -> Colour a<br />
pureColour ac | a > 0 = darken (recip a) (ac `over` mempty)<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnorhttps://wiki.haskell.org/index.php?title=Colour&diff=29045Colour2009-07-10T05:37:18Z<p>Roconnor: </p>
<hr />
<div>This page provides a short introduction to using the [http://hackage.haskell.org/package/colour colour package] on hackage.<br />
<br />
== The Colour data type ==<br />
<br />
The <hask>Colour a</hask> data type and its basic operations are found in the <hask>Data.Colour</hask> module. The type variable <hask>a</hask> is used to specify the numeric type used for the internal representation of the data. Typically one will use:<br />
<br />
<haskell><br />
Colour Double<br />
</haskell><br />
<br />
You may wish to make a type synonym for this type in your program if you will use it everywhere.<br />
<br />
You can always use the <hask>colourConvert</hask> to change to a different internal representation type.<br />
<br />
== Creating colours ==<br />
<br />
A collections of colours given by name can be found in the <hask>Data.Colour.Names</hask> module. There is also a <hask>readColourName</hask> to convert a string with one of these names into a colour. Be aware that the colour <hask>tan</hask> will conflict with the Prelude function unless you hide the Prelude function or import the module qualified.<br />
<br />
Another way to make a colour is by specifying an RGB triple. These functions can be found in the <hask>Data.Colour.SRGB</hask> library. For example, if you have three <hask>Word8</hask>s named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB24 red green blue<br />
</haskell><br />
<br />
will create the colour with those [http://en.wikipedia.org/wiki/SRGB sRGB] colour coordinates.<br />
<br />
If you have three <hask>Double</hask>s (or whatever you are using for your internal representation) named <hask>red</hask>, <hask>green</hask>, and <hask>blue</hask>, then <br />
<br />
<haskell><br />
sRGB red green blue<br />
</haskell><br />
<br />
will produce the colour with those colour coordinates. These <hask>Double</hask> should be in the range [0,1] otherwise the resulting colour would be out of gamut (a [http://en.wikipedia.org/wiki/Gamut colour gamut] is a collection of representable colours on a device, such as your monitor).<br />
<br />
Lastly, <hask>sRGB24read</hask> and <hask>sRGB24reads</hask> can create colour from string specifications of the form <hask>"#00aaff"</hask> or <hask>"00aaff"</hask>.<br />
<br />
== Manipulating Colours ==<br />
<br />
The colour operations are found in the <hask>Data.Colour</hask> module.<br />
The most common operation on colours is <hask>blend</hask>. For example, <br />
the function <br />
<br />
<haskell><br />
blend 0.25 red green<br />
</haskell><br />
<br />
will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.<br />
<br />
If you need to blend more than two colours, you can use multiple applications of <hask>blend</hask>, or you can use <hask>affineCombo</hask>. For example,<br />
<br />
<haskell><br />
affineCombo [(0.25,red),(0.5,green)] violet<br />
</haskell><br />
<br />
will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.<br />
<br />
Color intensity can be changed by using <hask>darken</hask>. For example,<br />
<br />
<haskell><br />
darken 0.4 turquoise<br />
</haskell><br />
<br />
will produce a turquoise that is only 40% of the intensity of normal turquoise.<br />
The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).<br />
<br />
Lastly, colours are instance of a [[Monoid]] so colours can be "added" by using <hask>mappend</hask> (and <hask>mempty</hask> is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using <hask>blend</hask> instead.<br />
<br />
== Getting colour coordinates out ==<br />
<br />
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
will produce a value of type <hask>RGB Double</hask>.<br />
<br />
=== RGB triples ===<br />
<br />
The type <hask>RGB</hask> is special type of (strict) triple used to store colour coordinates. The functions <hask>channelRed</hask>, <hask>channelGreen</hask>, and <hask>channelBlue</hask> can be used to access the three fields. The constructor <hask>RGB</hask> will created a such a triple. For example,<br />
<br />
<haskell><br />
RGB 0.5 0.4 0.6<br />
</haskell><br />
<br />
You might find the functions<br />
<br />
<haskell><br />
curryRGB :: (RGB a -> b) -> a -> a -> a -> b<br />
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b<br />
</haskell><br />
<br />
useful when working with functions that operate on RGB triples.<br />
<br />
=== Back to colour coordinates ===<br />
<br />
Recall that<br />
<br />
<haskell><br />
toSRGB chartreuse<br />
</haskell><br />
<br />
produces an <hask>RGB Double</hask>. The coordinates output by <hask>toSRGB</hask> will all be between 0 and 1 unless the colour is out of gamut.<br />
<br />
If you want to retrieve the colour coordinates as <hask>Word8</hask>s, use <hask>toSRGB24</hask><br />
<br />
<haskell><br />
toSRGB24 khaki<br />
</haskell><br />
<br />
will produce an <hask>RGB Word8</hask>. Out of gamut channels be clamped to either to the range 0 to 255.<br />
<br />
Lastly, the functions <hask>sRGB24show</hask> and <hask>sRGB24shows</hask> will produce colour strings of the form <hask>"#00aaff"</hask>.<br />
<br />
== Transparent Colour ==<br />
<br />
Colours that are semi transparent are represented by the <hask>AlphaColour a</hask> type found in <hask>Data.Colour</hask>. Again the <hask>a</hask> type parameter represents the data type used for the internal representation and would typically be <hask>Double</hask>.<br />
<br />
Opaque AlphaColours are created from Colours using <hask>opaque</hask>. For example.<br />
<br />
<haskell><br />
opaque goldenrod<br />
</haskell><br />
<br />
creates an opaque goldenrod. Semi transparent colours can be made using <hask>withOpacity</hask><br />
<br />
<haskell><br />
moccasin `withOpacity` 0.7<br />
</haskell><br />
<br />
creates a colour that is 70% opaque and hence 30% transparent.<br />
<br />
The value <hask>transparent</hask> is 100% transparent and <hask>transparent == anyColour `withOpacity` 0</hask>.<br />
<br />
Like regular colours, semi-transparent colours can be blended using <hask>blend</hask> and <hask>affineCombo</hask>. The function <hask>darken</hask> will darken a semi-transparent colour without affecting its opacity.<br />
<br />
To make an existing semi-transparent colour more transparent use <hask>dissolve</hask>. For example,<br />
<br />
<haskell><br />
dissolve 0.6 ac<br />
</haskell><br />
<br />
will return a semi-transparent colour that is 60% of the opacity of <hask>ac</hask>. Note that <br />
<br />
One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than <hask>x</hask> then you can safely use weights no more than <hask>(recip x)</hask>. Negative weights will also produce invalid "super-transparent" colours.<br />
<br />
<haskell><br />
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)<br />
</haskell><br />
<br />
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours <hask>acTop</hask> and <hask>acBottom</hask><br />
<br />
<haskell><br />
acTop `over` acBottom<br />
</haskell><br />
<br />
will produce the semi-transparent colour resulting from acTop being composited over top of <hask>acBottom</hask>. The bottom layer, <hask>acBottom</hask> can be a non-transparent colour (of type <hask>Colour</hask>). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque).<br />
<br />
Compositing is such important operation on semi-transparent colours, that it is the [[Monoid]] instance for <hask>AlphaColour a</hask>. The function <hask>mappend</hask> is <hask>over</hask>, and <hask>mempty</hask> is <hask>transparent</hask>.<br />
<br />
=== Getting semi-transparent coordinates ===<br />
<br />
The opacity of a semi-transparent colour can be retrieved by the <hask>alphaChannel</hask> function.<br />
<br />
The pure colour of a semi-transparent colour <hask>ac</hask> can be retrieved by first compositing the colour atop of black, then darkening by the reciprocal of the alpha channel.<br />
<br />
<haskell><br />
pureColour ac | a > 0 = darken (recip a) (ac `over` (mempty::Colour Double))<br />
| otherwise = error "transparent has no pure colour"<br />
where<br />
a = alphaChannel ac<br />
</haskell><br />
<br />
Note however, that transparent has no pure colour, and this case needs to be handled specially.<br />
<br />
This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from <hask>Colour</hask>. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.</div>Roconnor