[More removing of duplicate code from ch14 John Goerzen **20080405160443] { hunk ./en/ch04-defining-types.xml 804 + + The standard System.Time module makes good + use of record syntax. Here's a type defined in that module: + + +data CalendarTime = CalendarTime { + ctYear :: Int, + ctMonth :: Month, + ctDay, ctHour, ctMin, ctSec :: Int, + ctPicosec :: Integer, + ctWDay :: Day, + ctYDay :: Int, + ctTZName :: String, + ctTZ :: Int, + ctIsDST :: Bool +} + + + In the absence of record syntax, it would take quite some effort + to extract particular fields from a type like this. Records + make it easy to work with this sort of data. + hunk ./en/ch14-data.xml 35 + FIXME: need to integrate this elsewhere + hunk ./en/ch14-data.xml 48 - - With just three fields, the burden of pattern matching isn't all that - great. But what if you had a dozen or more? Named fields really - help out in that case. The standard Haskell library uses named - fields in System.Time.CalendarTime. Here's a - excerpt from its definition: - - -data CalendarTime = CalendarTime { - ctYear :: Int, - ctMonth :: Month, - ctDay, ctHour, ctMin, ctSec :: Int, - ctPicosec :: Integer, - ctWDay :: Day, - ctYDay :: Int, - ctTZName :: String, - ctTZ :: Int, - ctIsDST :: Bool -} - - - Named fields are a tremendous time saver here. If you have a - CalendarTime and want to extract just the year, - you can simply say ctYear ct rather than having to - match against 12 different fields in order. - - - - Polymorphic Types - - Sometimes you don't know in advance what the types of the data you - want to store will be. For instance, our - CustomColor2 type used ∬. But one could - certainly also represent color values as a &Float; or an &Integer;. - Haskell makes it possible to write generic code that - could work with any of those. Why not make the type generic as well? - - - Haskell has a well-known type that is defined just this way: &Maybe;. - It's defined in the prelude like this: - - -data Maybe a = Nothing | Just a - deriving (Eq, Ord) - - - This type is often used when the result of a function could be - a failure or some other invalid result (&Nothing;), or else a real value - (&Just;). For instance, if you are searching in a list for the first - result that matches search criteria, you will either find something - or you won't. If you do, you could get back the data wrapped in - &Just;, and if you don't, you could get back &Nothing;. - - - &Maybe; is a polymorphic type because its type depends on the type of - data that is encapsulated within it. You can, in fact, encapsulate - any type of data within it. Let's look at this - with &ghci;. - - &maybe.ghci:maybe1; - - Notice here that the type of &Nothing; is Maybe a, - but the type of Just "hi" is Maybe - [Char]. The reason for this is Haskell's type inference. - &Nothing; doesn't actually encapsulate any data, so it&emdash;by itself - &emdash;can be used with any &Just;. You can also give it an explicit type - to force it to behave a certain way, as we did with - Nothing :: Maybe [Char]. - - - Let's push the type system and see what it lets us do with &Maybe;. - - &maybe.ghci:maybe2; - - You can compare &Nothing; to a &Just; easily enough; that comparison - will of course always be false. The comparison between two &String;s - wrapped in &Just; also works. But the type checker wisely gives an - error on the last attempt, because you're trying to compare a - &String; to a number. - - - You'll see &Maybe; used quite a bit throughout this book, and in - Haskell code in general. - - - - A Final Word on Types - - We've shown you a lot of different ways to create your own types. - Note that, by using multiple constructors, you can effectively - combine various approaches in a single type. For instance, you could - say data Foo a = Bar | Baz Int | Other a if you so - desire. This may be useful in certain situations. - - - + }