diff --git a/1-getting-started.org b/1-getting-started.org index ade3530..46457ba 100644 --- a/1-getting-started.org +++ b/1-getting-started.org @@ -906,7 +906,7 @@ second case, we ask ~ghci~ to print the type of the expression without actually evaluating it, so it does not have to be so specific. It answers, in effect, "its type is numeric". We will see more of this style of type annotation in -[[file:6-using-typeclasses.org][Chapter 6, /Using Typeclasses/]]. +[[file:6-using-typeclasses.org][Chapter 6, Using Type Classes]]. ** A simple program diff --git a/10-parsing-a-binary-data-format.org b/10-parsing-a-binary-data-format.org index b10197e..951ab4c 100644 --- a/10-parsing-a-binary-data-format.org +++ b/10-parsing-a-binary-data-format.org @@ -653,8 +653,8 @@ ghci> treeMap (odd . length) tree Node (Leaf True) (Node (Leaf True) (Leaf False)) #+END_SRC -Haskell provides a well-known typeclass to further generalise -~treeMap~. This typeclass is named ~Functor~, and it defines one +Haskell provides a well-known type class to further generalise +~treeMap~. This type class is named ~Functor~, and it defines one function, ~fmap~. #+CAPTION: TreeMap.hs @@ -748,7 +748,7 @@ instance Functor Bar where #+END_SRC This says that we can only put a type ~a~ into a ~Foo~ if ~a~ is a -member of the ~Eq~ typeclass. However, the constraint renders it +member of the ~Eq~ type class. However, the constraint renders it impossible to write a ~Functor~ instance for ~Bar~. #+BEGIN_SRC screen diff --git a/11-testing-and-quality-assurance.org b/11-testing-and-quality-assurance.org index edebf58..5d2af26 100644 --- a/11-testing-and-quality-assurance.org +++ b/11-testing-and-quality-assurance.org @@ -101,7 +101,7 @@ tedious, and violates the moral code of the efficient functional programmer: let the machine do the work! To automate this the QuickCheck library comes with a set of data generators for all the basic Haskell data types. QuickCheck uses the ~Arbitrary~ -typeclass to present a uniform interface to (pseudo-)random data +type class to present a uniform interface to (pseudo-)random data generation with the type system used to resolve which generator to use. QuickCheck normally hides the data generation plumbing, however we can also run the generators by hand to get a sense for diff --git a/12-barcode-recognition.org b/12-barcode-recognition.org index 2bfd620..58ca519 100644 --- a/12-barcode-recognition.org +++ b/12-barcode-recognition.org @@ -559,7 +559,7 @@ luminance (r,g,b) = round (r' * 0.30 + g' * 0.59 + b' * 0.11) b' = fromIntegral b #+END_SRC -Haskell arrays are members of the ~Functor~ typeclass, so we can +Haskell arrays are members of the ~Functor~ type class, so we can simply use ~fmap~ to turn an entire image, or a single scanline, from colour into greyscale. diff --git a/13-data-structures.org b/13-data-structures.org index d8c1aff..a8f0f1e 100644 --- a/13-data-structures.org +++ b/13-data-structures.org @@ -488,8 +488,8 @@ is. We've shown you a lot of ways to use that power. Here's a chance to really see that in action. Back in [[file:6-using-typeclasses.org::*Numeric Types][the section called "Numeric Types"]] -typeclasses that come with Haskell. Let's see what we can do by -defining new types and utilizing the numeric typeclasses to +type classes that come with Haskell. Let's see what we can do by +defining new types and utilizing the numeric type classes to integrate them with basic mathematics in Haskell. Let's start by thinking through what we'd like to see out of @@ -701,7 +701,7 @@ as valid as a ~SymbolicManip Int~ as it as an ~Int~. From here, then, our task is simple: extend the ~SymbolicManip~ type to be able to represent all the operations we will want to perform, implement instances of it for the other numeric -typeclasses, and implement our own instance of ~Show~ for +type classes, and implement our own instance of ~Show~ for ~SymbolicManip~ that renders this tree in a more accessible fashion. @@ -942,7 +942,7 @@ Now it may become clear why we use a ~SymbolicManip~ instead of a multiplication occur, the unit of measure also changes. For instance, if we multiply 5 meters by 2 meters, we obtain 10 square meters. We force the units for addition to match, and implement -subtraction in terms of addition. Let's look at more typeclass +subtraction in terms of addition. Let's look at more type class instances for ~Units~. #+CAPTION: num.hs @@ -1334,7 +1334,7 @@ binary operator and zero as the identity value, integers form a monoid. With multiplication as the binary operator and one as the identity value, integers form a different monoid. -Monoids are ubiquitous in Haskell[fn:3]. The ~Monoid~ typeclass is +Monoids are ubiquitous in Haskell[fn:3]. The ~Monoid~ type class is defined in the ~Data.Monoid~ module. #+CAPTION: Monoid.hs @@ -1545,7 +1545,7 @@ If we want to create a list from a ~Seq~, we must use the import qualified Data.Foldable as Foldable #+END_SRC -This module defines a typeclass, ~Foldable~, which ~Seq~ +This module defines a type class, ~Foldable~, which ~Seq~ implements. #+BEGIN_SRC screen @@ -1574,7 +1574,7 @@ well. ** Footnotes [fn:1] The type we use for the key must be a member of the ~Eq~ -typeclass. +type class. [fn:2] Non-strict evaluation makes the cost calculation more subtle. We only pay for an append if we actually use the diff --git a/14-using-parsec.org b/14-using-parsec.org index 2cb41aa..fe52a8c 100644 --- a/14-using-parsec.org +++ b/14-using-parsec.org @@ -644,7 +644,7 @@ $ runhaskell csv7.hs < test.csv ** Parsec and MonadPlus Parsec's ~GenParser~ monad is an instance of the ~MonadPlus~ -typeclass that we introduced in +type class that we introduced in [[file:16-programming-with-monads.org::*Looking for alternatives][the section called "Looking for alternatives"]] represents a parse failure, while ~mplus~ combines two alternative parses into one, using ~(<|>)~. @@ -786,7 +786,7 @@ effort of coming to grips with the idea. ** Applicative functors for parsing The standard Haskell libraries include a module named -~Control.Applicative~, which defines a typeclass named +~Control.Applicative~, which defines a type class named ~Applicative~, which represents an /applicative functor/. Because every applicative functor is also a functor they are represented as a hierarchy. diff --git a/15-monads.org b/15-monads.org index 6f24a23..7e57c7c 100644 --- a/15-monads.org +++ b/15-monads.org @@ -224,11 +224,11 @@ programming patterns have a monadic structure: passing around implicit data, or short-circuiting a chain of evaluations if one fails, to choose but two. -** The Monad typeclass +** The Monad type class We can capture the notions of chaining and injection, and the -types that we want them to have, in a Haskell typeclass. The -standard ~Prelude~ already defines just such a typeclass, named +types that we want them to have, in a Haskell type class. The +standard ~Prelude~ already defines just such a type class, named ~Monad~. #+BEGIN_SRC haskell @@ -263,7 +263,7 @@ behavior to its name is that it /returns/ a pure value (of type ~a~) into a monad (of type ~m a~). While ~(>>=)~ and ~return~ are the core functions of the ~Monad~ -typeclass, it also defines two other functions. The first is +type class, it also defines two other functions. The first is ~(>>)~. Like ~(>>=)~, it performs chaining, but it ignores the value on the left. @@ -367,10 +367,10 @@ familiar with. These aren't formal terms, but they're in common use, so it's helpful to know about them. - "Monadic" simply means "pertaining to monads". A monadic /type/ - is an instance of the ~Monad~ typeclass; a monadic /value/ has a + is an instance of the ~Monad~ type class; a monadic /value/ has a monadic type. - When we say that a type "is a monad", this is really a shorthand - way of saying that it's an instance of the ~Monad~ typeclass. + way of saying that it's an instance of the ~Monad~ type class. Being an instance of ~Monad~ gives us the necessary monadic triple of type constructor, injection function, and chaining function. @@ -388,7 +388,7 @@ use, so it's helpful to know about them. In our introduction to monads, we showed how some pre-existing code was already monadic in form. Now that we are beginning to -grasp what a monad is, and we've seen the ~Monad~ typeclass, let's +grasp what a monad is, and we've seen the ~Monad~ type class, let's build a monad with foreknowledge of what we're doing. We'll start out by defining its interface, then we'll put it to use. Once we have those out of the way, we'll finally build it. @@ -461,7 +461,7 @@ runLogger :: Logger a -> (a, Log) *** Controlled escape -The ~Monad~ typeclass doesn't provide any means for values to +The ~Monad~ type class doesn't provide any means for values to escape their monadic shackles. We can inject a value into a monad using ~return~. We can extract a value from a monad using ~(>>=)~ but the function on the right, which can see an unwrapped value, @@ -658,7 +658,7 @@ functor, calling the function on it, and rewrapping the result with the same constructor. We do exactly the same thing with a monad. Because the ~Monad~ -typeclass already provides the ~(>>=)~ and ~return~ functions that +type class already provides the ~(>>=)~ and ~return~ functions that know how to unwrap and wrap a value, the ~liftM~ function doesn't need to know any details of a monad's implementation. @@ -670,7 +670,7 @@ liftM f m = m >>= \i -> #+END_SRC When we declare a type to be an instance of the ~Functor~ -typeclass, we have to write our own version of ~fmap~ specially +type class, we have to write our own version of ~fmap~ specially tailored to that type. By contrast, ~liftM~ doesn't need to know anything of a monad's internals, because they're abstracted by ~(>>=)~ and ~return~. We only need to write it once, with the @@ -849,7 +849,7 @@ flavours, each with different levels of strictness. Our ~Logger~ monad is a specialised version of the standard ~Writer~ monad, which can be found in the ~Control.Monad.Writer~ module of the ~mtl~ package. We will present a ~Writer~ example in -[[file:16-programming-with-monads.org::*Using typeclasses][the section called "Using typeclasses"]] +[[file:16-programming-with-monads.org::*Using type classes][the section called "Using type classes"]] ** The Maybe monad @@ -1631,14 +1631,14 @@ rand = getStdRandom (randomR (0, maxBound)) (The ~randomR~ function takes an inclusive range within which the generated random value should lie.) -The ~System.Random~ module provides a typeclass, ~RandomGen~, that +The ~System.Random~ module provides a type class, ~RandomGen~, that lets us define new sources of random ~Int~ values. The type ~StdGen~ is the standard ~RandomGen~ instance. It generates pseudorandom values. If we had an external source of truly random data, we could make it an instance of ~RandomGen~ and get truly random, instead of merely pseudorandom, values. -Another typeclass, ~Random~, indicates how to generate random +Another type class, ~Random~, indicates how to generate random values of a particular type. The module defines ~Random~ instances for all of the usual simple types. @@ -1882,7 +1882,7 @@ conventionally named ~join~. If we had definitions of ~join~ and ~fmap~, we wouldn't need to write a definition of ~(>>=)~ for every monad, because it would be completely generic. Here's what an alternative definition of the -~Monad~ typeclass might look like, along with a definition of +~Monad~ type class might look like, along with a definition of ~(>>=)~. #+BEGIN_SRC haskell diff --git a/16-programming-with-monads.org b/16-programming-with-monads.org index aefa259..1594898 100644 --- a/16-programming-with-monads.org +++ b/16-programming-with-monads.org @@ -237,7 +237,7 @@ ghci> allBusinessPhones nils ["+47-922-12-121","+47-922-25-551"] #+END_SRC -Haskell's ~Control.Monad~ module defines a typeclass, ~MonadPlus~, +Haskell's ~Control.Monad~ module defines a type class, ~MonadPlus~, that lets us abstract the common pattern out of our ~case~ expressions. @@ -343,7 +343,7 @@ Just 1 *** Rules for working with ~MonadPlus~ -Instances of the ~MonadPlus~ typeclass must follow a few simple +Instances of the ~MonadPlus~ type class must follow a few simple rules, in addition to the usual monad rules. An instance must /short circuit/ if ~mzero~ appears on the left of @@ -364,11 +364,11 @@ of a sequence expression. *** Failing safely with ~MonadPlus~ When we introduced the ~fail~ function in -[[file:15-monads.org::*The Monad typeclass][the section called "The Monad typeclass"]] +[[file:15-monads.org::*The Monad type class][the section called "The Monad type class"]] warn against its use: in many monads, it's implemented as a call to ~error~, which has unpleasant consequences. -The ~MonadPlus~ typeclass gives us a gentler way to fail a +The ~MonadPlus~ type class gives us a gentler way to fail a computation, without ~fail~ or ~error~ blowing up in our faces. The rules that we introduced above allow us to introduce an ~mzero~ into our code wherever we need to, and computation will @@ -527,12 +527,12 @@ file, before the module header. #+END_SRC Usually, we can only automatically derive instances of a handful -of standard typeclasses, such as ~Show~ and ~Eq~. As its name +of standard type classes, such as ~Show~ and ~Eq~. As its name suggests, the ~GeneralizedNewtypeDeriving~ extension broadens our -ability to derive typeclass instances, and it is specific to +ability to derive type class instances, and it is specific to ~newtype~ declarations. If the type we're wrapping is an instance -of any typeclass, the extensions can automatically make our new -type an instance of that typeclass as follows. +of any type class, the extensions can automatically make our new +type an instance of that type class as follows. #+CAPTION: Supply.hs #+BEGIN_SRC haskell @@ -546,7 +546,7 @@ derive a ~Monad~ instance for us. What we gain here is very useful beyond just this example. We can use ~newtype~ to wrap any underlying type; we selectively expose -only those typeclass instances that we want; and we expend almost +only those type class instances that we want; and we expend almost no effort to create these narrower, more specialised types. Sadly currently GHC is not able to automatically derive the @@ -683,7 +683,7 @@ ghci> second odd ('a',1) #+END_SRC (Indeed, we already encountered ~second~, in -[[file:6-using-typeclasses.org::*JSON typeclasses without overlapping instances][the section called "JSON typeclasses without overlapping instances"]] +[[file:6-using-typeclasses.org::*JSON type classes without overlapping instances][the section called "JSON type classes without overlapping instances"]] We can use ~first~ to golf our definition of ~randomsIO~, turning it into a one-liner. @@ -713,7 +713,7 @@ One simple and effective way that we could deal with this is to provide ~Supply~ with a better source of random numbers. Let's set this idea aside, though, and consider an alternative approach, one that is useful in many settings. We will separate the actions we -can perform with the monad from how it works using a typeclass. +can perform with the monad from how it works using a type class. #+CAPTION: SupplyClass.hs #+BEGIN_SRC haskell @@ -727,21 +727,21 @@ class (Monad m) => MonadSupply s m | m -> s where next :: m (Maybe s) #+END_SRC -This typeclass defines the interface that any supply monad must +This type class defines the interface that any supply monad must implement. It bears careful inspection, since it uses several unfamiliar Haskell language extensions. We will cover each one in the sections that follow. -*** Multi-parameter typeclasses +*** Multi-parameter type classes -How should we read the snippet ~MonadSupply s m~ in the typeclass? +How should we read the snippet ~MonadSupply s m~ in the type class? If we add parentheses, an equivalent expression is ~(MonadSupply s) m~, which is a little clearer. In other words, given some type variable ~m~ that is a monad, we can make it an -instance of the typeclass ~MonadSupply s~. unlike a regular -typeclass, this one has a /parameter/. +instance of the type class ~MonadSupply s~. unlike a regular +type class, this one has a /parameter/. -As this language extension allows a typeclass to have more than +As this language extension allows a type class to have more than one parameter, its name is ~MultiParamTypeClasses~. The parameter ~s~ serves the same purpose as the ~Supply~ type's parameter of the same name: it represents the type of the values handed out by @@ -777,7 +777,7 @@ use with it. If we were to omit the functional dependency, the type checker would simply give up with an error message. It's hard to picture what the relationship between ~m~ and ~s~ -really means, so let's look at an instance of this typeclass. +really means, so let's look at an instance of this type class. #+CAPTION: SupplyClass.hs #+BEGIN_SRC haskell @@ -788,7 +788,7 @@ instance MonadSupply s (S.Supply s) where Here, the type variable ~m~ is replaced by the type ~S.Supply s~. Thanks to our functional dependency, the type checker now knows that when it sees a type ~S.Supply s~, the type can be used as an -instance of the typeclass ~MonadSupply s~. +instance of the type class ~MonadSupply s~. If we didn't have a functional dependency, the type checker would not be able to figure out the relationship between the type @@ -802,7 +802,7 @@ To strip away one final layer of abstraction, consider the type this an instance of ~MonadSupply s~. However, if we tried to write code using this instance, the compiler would not be able to figure out that the type's ~Int~ parameter needs to be the same as the -typeclass's ~s~ parameter, and it would report an error. +type class's ~s~ parameter, and it would report an error. Functional dependencies can be tricky to understand, and once we move beyond simple uses, they often prove difficult to work with @@ -812,7 +812,7 @@ little trouble. *** Rounding out our module -If we save our typeclass and instance in a source file named +If we save our type class and instance in a source file named ~SupplyClass.hs~, we'll need to add a module header such as the following. @@ -962,7 +962,7 @@ courtesy of the ~Reader~ monad. ** A return to automated deriving Now that we know about the ~Reader~ monad, let's use it to create -an instance of our ~MonadSupply~ typeclass. To keep our example +an instance of our ~MonadSupply~ type class. To keep our example simple, we'll violate the spirit of ~MonadSupply~ here: our ~next~ action will always return the same value, instead of always returning a different value. @@ -974,7 +974,7 @@ sense. Instead, we create a ~newtype~ based on ~Reader~. The ~newtype~ hides the fact that we're using ~Reader~ internally. We must now -make our type an instance of both of the typeclasses we care +make our type an instance of both of the type classes we care about. With the ~GeneralizedNewtypeDeriving~ extension enabled, GHC will do most of the hard work for us. @@ -1065,22 +1065,22 @@ ghci> runMS xy 2 4 #+END_SRC -Like our ~MonadSupply~ typeclass and ~Supply~ monad, almost all of +Like our ~MonadSupply~ type class and ~Supply~ monad, almost all of the common Haskell monads are built with a split between interface and implementation. For example, the ~get~ and ~put~ functions that we introduced as "belonging to" the ~State~ monad are -actually methods of the ~MonadState~ typeclass; the ~State~ type +actually methods of the ~MonadState~ type class; the ~State~ type is an instance of this class. Similarly, the standard ~Reader~ monad is an instance of the -~MonadReader~ typeclass, which specifies the ~ask~ method. +~MonadReader~ type class, which specifies the ~ask~ method. While the separation of interface and implementation that we've discussed above is appealing for its architectural cleanliness, it has important practical applications that will become clearer later. When we start combining monads in [[file:18-monad-transformers.org][Chapter 18, /Monad transformers/]], we will save a lot of effort -through the use of ~GeneralizedNewtypeDeriving~ and typeclasses. +through the use of ~GeneralizedNewtypeDeriving~ and type classes. ** Hiding the ~IO~ monad @@ -1214,7 +1214,7 @@ us to write solid code in the common case, not to make corner cases impossible. Let's thus give ourselves a way out. The ~Control.Monad.Trans~ module defines a "standard escape -hatch", the ~MonadIO~ typeclass. This defines a single function, +hatch", the ~MonadIO~ type class. This defines a single function, ~liftIO~, which lets us embed an ~IO~ action in another monad. #+BEGIN_SRC screen @@ -1227,7 +1227,7 @@ class Monad m => MonadIO (m :: * -> *) where instance [safe] MonadIO IO -- Defined in ‘Control.Monad.IO.Class’ #+END_SRC -Our implementation of this typeclass is trivial: we just wrap ~IO~ +Our implementation of this type class is trivial: we just wrap ~IO~ with our data constructor. #+CAPTION: HandleIO.hs @@ -1257,14 +1257,14 @@ usual strategy. We avoided that here simply to separate the presentation of the earlier material from that of ~MonadIO~. #+END_TIP -*** Using typeclasses +*** Using type classes The disadvantage of hiding ~IO~ in another monad is that we're still tied to a concrete implementation. If we want to swap ~HandleIO~ for some other monad, we must change the type of every action that uses ~HandleIO~. -As an alternative, we can create a typeclass that specifies the +As an alternative, we can create a type class that specifies the interface we want from a monad that manipulates files. #+CAPTION: MonadHandle.hs @@ -1343,16 +1343,16 @@ ghci> safeHello "hello to my fans in domestic surveillance" ghci> removeFile "hello to my fans in domestic surveillance" #+END_SRC -The beauty of the typeclass approach is that we can swap one +The beauty of the type class approach is that we can swap one underlying monad for another without touching much code, as most of our code doesn't know or care about the implementation. For instance, we could replace ~IO~ with a monad that compresses files as it writes them out. -Defining a monad's interface through a typeclass has a further +Defining a monad's interface through a type class has a further benefit. It lets other people hide our implementation in a ~newtype~ wrapper, and automatically derive instances of just the -typeclasses they want to expose. +type classes they want to expose. *** Isolation and testing @@ -1387,7 +1387,7 @@ Although we already developed a ~Logger~ type in [[file:15-monads.org::*Using a new monad: show your work!][the section called "Using a new monad: show your work!"]] we'll use the standard, and more general, ~Writer~ monad. Like other ~mtl~ monads, the API provided by ~Writer~ is defined in a -typeclass, in this case ~MonadWriter~. Its most useful method is +type class, in this case ~MonadWriter~. Its most useful method is ~tell~, which logs a value. #+BEGIN_SRC screen @@ -1462,9 +1462,9 @@ type from the ~Data.Sequence~ module, which we introduced in *** Arbitrary I/O revisited -If we use the typeclass approach to restricting ~IO~, we may still +If we use the type class approach to restricting ~IO~, we may still want to retain the ability to perform arbitrary I/O actions. We -might try adding ~MonadIO~ as a constraint on our typeclass. +might try adding ~MonadIO~ as a constraint on our type class. #+CAPTION: MonadHandleIO.hs #+BEGIN_SRC haskell @@ -1482,7 +1482,7 @@ This approach has a problem, though: the added ~MonadIO~ constraint loses us the ability to test our code in a pure environment, because we can no longer tell whether a test might have damaging side effects. The alternative is to move this -constraint from the typeclass, where it "infects" all functions, +constraint from the type class, where it "infects" all functions, to only those functions that really need to perform I/O. #+CAPTION: MonadHandleIO.hs diff --git a/18-monad-transformers.org b/18-monad-transformers.org index 9410ff4..b7b3b0a 100644 --- a/18-monad-transformers.org +++ b/18-monad-transformers.org @@ -84,7 +84,7 @@ We will find the going easier if we look at the types involved. The normal ~Writer~ monad has two type parameters, so it's more properly written ~Writer w a~. The first parameter ~w~ is the type of the values to be recorded, and ~a~ is the usual type that the -~Monad~ typeclass requires. Thus ~Writer [(FilePath, Int)] a~ is a +~Monad~ type class requires. Thus ~Writer [(FilePath, Int)] a~ is a writer monad that records a list of directory names and sizes. The ~WriterT~ transformer has a similar structure, but it adds @@ -156,12 +156,12 @@ transformers, ~IO~ will always be at the bottom of the stack. ** Common patterns in monads and monad transformers Most of the monads and monad transformers in the ~mtl~ library -follow a few common patterns around naming and typeclasses. +follow a few common patterns around naming and type classes. To illustrate these rules, we will focus on a single straightforward monad: the reader monad. The reader monad's API is -detailed by the ~MonadReader~ typeclass. Most ~mtl~ monads have -similarly named typeclasses: ~MonadWriter~ defines the API of the +detailed by the ~MonadReader~ type class. Most ~mtl~ monads have +similarly named type classes: ~MonadWriter~ defines the API of the writer monad, and so on. #+BEGIN_SRC haskell @@ -175,7 +175,7 @@ The type variable ~r~ represents the immutable state that the of the ~MonadReader~ class, as is the ~ReaderT r m~ monad transformer. Again, this pattern is repeated by other ~mtl~ monads: there usually exist both a concrete monad and a -transformer, each of which are instances of the typeclass that +transformer, each of which are instances of the type class that defines the monad's API. Returning to the specifics of the ~Reader~ monad, we haven't @@ -211,7 +211,7 @@ Loading package mtl-1.1.0.0 ... linking ... done. When the underlying monad ~m~ is an instance of ~MonadIO~, the ~mtl~ library provides an instance for ~ReaderT r m~, and also for -a number of other typeclasses. Here are a few. +a number of other type classes. Here are a few. #+BEGIN_SRC haskell instance (Monad m) => Functor (ReaderT r m) where @@ -399,7 +399,7 @@ magical that the compiler can derive all of these instances for us. How does this work? Earlier, we mentioned that the ~mtl~ library provides instances of -a number of typeclasses for each monad transformer. For example, +a number of type classes for each monad transformer. For example, the ~IO~ monad implements ~MonadIO~. If the underlying monad is an instance of ~MonadIO~, ~mtl~ makes ~StateT~ an instance, too, and likewise for ~ReaderT~. @@ -407,7 +407,7 @@ likewise for ~ReaderT~. There is thus no magic going on: the top-level monad transformer in the stack is an instance of all of the type classes that we're rederiving with our ~deriving~ clause. This is a consequence of -~mtl~ providing a carefully coordinated set of typeclasses and +~mtl~ providing a carefully coordinated set of type classes and instances that fit together well. There is nothing more going on than the usual automatic derivation that we can perform with ~newtype~ declarations. @@ -444,7 +444,7 @@ newtype CustomT m a = ... In the framework that ~mtl~ provides, each monad transformer in the stack makes the API of a lower level available by providing -instances of a host of typeclasses. We could follow this pattern, +instances of a host of type classes. We could follow this pattern, and write a number of boilerplate instances. #+BEGIN_SRC haskell @@ -463,9 +463,9 @@ only care that the stack as a whole is an instance of ~MonadReader~, without knowing or caring about which layer provides the /real/ implementation. -Instead of relying on all of these typeclass instances to work for +Instead of relying on all of these type class instances to work for us behind the scenes, we can be explicit. The ~MonadTrans~ -typeclass defines a useful function named ~lift~. +type class defines a useful function named ~lift~. #+BEGIN_SRC screen ghci> :m +Control.Monad.Trans @@ -497,7 +497,7 @@ type App = ReaderT AppConfig (StateT AppState IO) #+END_SRC If we want to access the ~AppState~ carried by the ~StateT~, we -would usually rely on ~mtl~'s typeclasses and instances to handle +would usually rely on ~mtl~'s type classes and instances to handle the plumbing for us. #+CAPTION: UglyStack.hs @@ -521,7 +521,7 @@ with cleaner code, but this is not always possible. *** When explicit lifting is necessary One case in which we /must/ use ~lift~ is when we create a monad -transformer stack in which instances of the same typeclass appear +transformer stack in which instances of the same type class appear at multiple levels. #+CAPTION: StackStack.hs @@ -529,7 +529,7 @@ at multiple levels. type Foo = StateT Int (State String) #+END_SRC -If we try to use the ~put~ action of the ~MonadState~ typeclass, +If we try to use the ~put~ action of the ~MonadState~ type class, the instance we will get is that of ~StateT Int~, because it's at the top of the stack. @@ -600,11 +600,11 @@ bindMT :: (Monad m) => MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b #+END_SRC To understand this type signature, hark back to our discussion -of multi-parameter typeclasses in -[[file:16-programming-with-monads.org::*Multi-parameter typeclasses][the section called "Multi-parameter typeclasses"]] +of multi-parameter type classes in +[[file:16-programming-with-monads.org::*Multi-parameter type classes][the section called "Multi-parameter type classes"]] intend to make a ~Monad~ instance is the /partial type/ ~MaybeT m~: this has the usual single type parameter, ~a~, that -satisfies the requirements of the ~Monad~ typeclass. +satisfies the requirements of the ~Monad~ type class. The trick to understanding the body of our ~(>>=)~ implementation is that everything inside the ~do~ block executes in the @@ -673,10 +673,10 @@ The underlying monad starts out with a type parameter of a: we we need, ~Maybe a~. We then hide the monad with our ~MaybeT~ constructor. -*** More typeclass instances +*** More type class instances Once we have an instance for ~MonadTrans~ defined, we can use it -to define instances for the umpteen other ~mtl~ typeclasses. +to define instances for the umpteen other ~mtl~ type classes. #+CAPTION: MaybeT.hs #+BEGIN_SRC haskell @@ -690,7 +690,7 @@ instance (MonadState s m) => MonadState s (MaybeT m) where -- ... and so on for MonadReader, MonadWriter, etc ... #+END_SRC -Because several of the ~mtl~ typeclasses use functional +Because several of the ~mtl~ type classes use functional dependencies, some of our instance declarations require us to considerably relax GHC's usual strict type checking rules. (If we were to forget any of these directives, the compiler would @@ -967,7 +967,7 @@ by ~mtl~, some deficiencies start to show. For example, if we create a new monad transformer ~FooT~ and want to follow the same pattern as ~mtl~, we'll have it implement a -typeclass ~MonadFoo~. If we really want to integrate it cleanly +type class ~MonadFoo~. If we really want to integrate it cleanly into the ~mtl~, we'll have to provide instances for each of the dozen or so ~mtl~ type classes. diff --git a/19-error-handling.org b/19-error-handling.org index 7e0c4d8..2752727 100644 --- a/19-error-handling.org +++ b/19-error-handling.org @@ -816,7 +816,7 @@ data SqlError = SqlError {seState :: String, deriving (Eq, Show, Read, Typeable) #+END_EXAMPLE -By deriving the ~Typeable~ typeclass, we've made this type +By deriving the ~Typeable~ type class, we've made this type available for dynamically typed programming. In order for GHC to automatically generate a ~Typeable~ instance, we had to enable the ~DeriveDataTypeable~ language extension[fn:5]. @@ -964,7 +964,7 @@ bounced out to the ~IO~ monad. #+END_NOTE As with other ~mtl~ monads, the interface that ~ErrorT~ provides -is defined by a typeclass. +is defined by a type class. #+CAPTION: MonadError.hs #+BEGIN_EXAMPLE @@ -979,7 +979,7 @@ class (Monad m) => MonadError e m | m -> e where The type variable ~e~ represents the error type we want to use. Whatever our error type is, we must make it an instance of the -~Error~ typeclass. +~Error~ type class. #+CAPTION: MonadError.hs #+BEGIN_EXAMPLE @@ -994,7 +994,7 @@ class Error a where The ~strMsg~ function is used by ~ErrorT~'s implementation of ~fail~. It throws ~strMsg~ as an exception, passing it the string argument it received. As for ~noMsg~, it is used to provide an -~mzero~ implementation for the ~MonadPlus~ typeclass. +~mzero~ implementation for the ~MonadPlus~ type class. To support the ~strMsg~ and ~noMsg~ functions, our ~ParseError~ type will have a ~Chatty~ constructor. This will be used as the diff --git a/2-types-and-functions.org b/2-types-and-functions.org index 4f50f21..4347532 100644 --- a/2-types-and-functions.org +++ b/2-types-and-functions.org @@ -141,8 +141,8 @@ Static typing can occasionally make it difficult to write some useful kinds of code. In languages like Python, "duck typing" is common, where an object acts enough like another to be used as a substitute for it[fn:1]. Fortunately, Haskell's system of -/typeclasses/, which we will cover in -[[file:6-using-typeclasses.org][Chapter 6, /Using Typeclasses/]], provides almost all of the +/type classes/, which we will cover in +[[file:6-using-typeclasses.org][Chapter 6, Using Type Classes]], provides almost all of the benefits of dynamic typing, in a safe and convenient form. Haskell has some support for programming with truly dynamic types, though it is not quite as easy as in a language that wholeheartedly @@ -1277,7 +1277,7 @@ point numbers. Haskell deliberately avoids even this kind of simple automatic coercion. This is not the whole story of polymorphism in Haskell: we'll -return to the subject in [[file:6-using-typeclasses.org][Chapter 6, /Using Typeclasses/]]. +return to the subject in [[file:6-using-typeclasses.org][Chapter 6, Using Type Classes]]. *** Reasoning about polymorphic functions diff --git a/20-systems-programming-in-haskell.org b/20-systems-programming-in-haskell.org index 1615d56..56070a7 100644 --- a/20-systems-programming-in-haskell.org +++ b/20-systems-programming-in-haskell.org @@ -314,10 +314,10 @@ highlighted: is not necessary to put accurate values into these fields, unless your later calculations will depend upon them. - All of these three types are members of the ~Eq~, ~Ord~, ~Read~, - and ~Show~ typeclasses. In addition, ~Month~ and ~Day~ are - declared as members of the ~Enum~ and ~Bounded~ typeclasses. For - more information on these typeclasses, refer to - [[file:6-using-typeclasses.org::*Important Built-In Typeclasses][the section called "Important Built-In Typeclasses"]] + and ~Show~ type classes. In addition, ~Month~ and ~Day~ are + declared as members of the ~Enum~ and ~Bounded~ type classes. For + more information on these type classes, refer to + [[file:6-using-typeclasses.org::*Important%20Built-In%20Type%20Classes][the section called "Important Built-In Type Classes"]] You can generate ~CalendarTime~ values several ways. You could start by converting a ~ClockTime~ to a ~CalendarTime~ such as @@ -830,7 +830,7 @@ ghci> runIO $ ("ls", ["/etc"]) -|- ("grep", ["m.*ap"]) -|- ("tr", ["a-z", "A-Z"] We start by running a simple command, ~pwd~, which just prints the name of the current working directory. We pass ~[]~ for the list of arguments, because ~pwd~ doesn't need any arguments. Due to the -typeclasses used, Haskell can't infer the type of ~[]~, so we +type classes used, Haskell can't infer the type of ~[]~, so we specifically mention that it's a ~String~. Then we get into more complex commands. We run ~ls~, sending it @@ -844,7 +844,7 @@ Let's look at the program. The very first line has a special ~OPTIONS_GHC~ clause. This is the same as passing ~-fglasgow-exts~ to ~ghc~ or ~ghci~. We are using a GHC extension that permits us to use a ~(String, [String])~ type as an instance of a -typeclass.[fn:5] By putting it in the source file, we don't have +type class.[fn:5] By putting it in the source file, we don't have to remember to specify it every time we use this module. After the ~import~ lines, we define a few types. First, we define @@ -1151,7 +1151,7 @@ instance RunResult (IO ()) where run cmd = run cmd >>= checkResult instance RunResult (IO ProcessStatus) where - run cmd = + run cmd = do res <- setUpCommand cmd -- Process its output @@ -1207,7 +1207,7 @@ runIO = run ------------------------------------------------------------ cd :: FilePath -> IO () cd = setCurrentDirectory - + {- | Takes a string and sends it on as standard output. The input to this function is never read. -} echo :: String -> String -> String @@ -1254,7 +1254,7 @@ Here's what has changed: - New ~CommandLike~ instances for ~String -> IO String~ and various other types that are implemented in terms of this one. These process Haskell functions as commands. -- A new ~RunResult~ typeclass that defines a function ~run~ that +- A new ~RunResult~ type class that defines a function ~run~ that returns information about the command in many different ways. See the comments in the source for more information. ~runIO~ is now just an alias for one particular ~RunResult~ instance. diff --git a/21-using-databases.org b/21-using-databases.org index 0924755..cf2524c 100644 --- a/21-using-databases.org +++ b/21-using-databases.org @@ -88,7 +88,7 @@ you will call anything from a backend driver module directly. The database connection function will return a database handle. The precise type of this handle may vary from one driver to the next, but it will always be an instance of the ~IConnection~ -typeclass. All of the functions you will use to operate on +type class. All of the functions you will use to operate on databases will work with any type that is an instance of ~IConnection~. When you're done talking to the database, call the ~disconnect~ function. It will disconnect you from the database. diff --git a/24-concurrent-and-multicore-programming.org b/24-concurrent-and-multicore-programming.org index 8c5edae..37a6e2e 100644 --- a/24-concurrent-and-multicore-programming.org +++ b/24-concurrent-and-multicore-programming.org @@ -953,7 +953,7 @@ a meaningful value. Of course, in many cases we will need to force the evaluation of individual elements of the list, too. Below, we will discuess a -typeclass-based solution to this problem. +type class-based solution to this problem. *** What promises does par make? @@ -1346,7 +1346,7 @@ rwhnf x = x `seq` () #+END_SRC To evaluate a value to normal form, the module provides a -typeclass with a method named ~rnf~. +type class with a method named ~rnf~. #+CAPTION: Strat.hs #+BEGIN_SRC haskell @@ -1366,7 +1366,7 @@ data"; and so on. For the basic types, such as ~Int~, weak head normal form and normal form are the same thing, which is why the ~NFData~ -typeclass uses ~rwhnf~ as the default implementation of ~rnf~. For +type class uses ~rwhnf~ as the default implementation of ~rnf~. For many common types, the ~Control.Parallel.Strategies~ module provides instances of ~NFData~. diff --git a/26-building-a-bloom-filter.org b/26-building-a-bloom-filter.org index dca6c21..388f53f 100644 --- a/26-building-a-bloom-filter.org +++ b/26-building-a-bloom-filter.org @@ -285,7 +285,7 @@ new hash numBits = MB hash `liftM` newArray (0,numBits-1) False #+END_SRC Most of the methods of ~STUArray~ are actually implementations of -the ~MArray~ typeclass, which is defined in the +the ~MArray~ type class, which is defined in the ~Data.Array.MArray~ module. Our ~length~ function is slightly complicated by two factors. We @@ -407,7 +407,7 @@ execution with freezing. Given an action that returns an ~STUArray~, it executes the action using ~runST~; freezes the ~STUArray~ that it returns; and returns that as a ~UArray~. -The ~MArray~ typeclass provides a ~freeze~ function that we could +The ~MArray~ type class provides a ~freeze~ function that we could use instead, but ~runSTUArray~ is both more convenient and more efficient. The efficiency lies in the fact that ~freeze~ must copy the underlying data from the ~STUArray~ to the new ~UArray~, to @@ -435,7 +435,7 @@ easyList :: (Hashable a) Here is a possible "friendlier" way to create a Bloom filter. It leaves responsibility for hashing values in the hands of a -typeclass, Hashable. It lets us configure the Bloom filter based +type class, Hashable. It lets us configure the Bloom filter based on a parameter that is easier to understand, namely the rate of false positives that we are willing to tolerate. And it chooses the size of the filter for us, based on the desired false positive @@ -609,7 +609,7 @@ and ~p2~, we only need to ~peek~ the pointer ~sp~ to retrieve the computed hash. We don't want clients of this module to be stuck fiddling with -low-level details, so we use a typeclass to provide a clean, +low-level details, so we use a type class to provide a clean, high-level interface. #+CAPTION: BloomFilter/Hash.hs @@ -624,7 +624,7 @@ hash = hashSalt 0x106fc397cf62f64d3 #+END_SRC We also provide a number of useful implementations of this -typeclass. To hash basic types, we must write a little boilerplate +type class. To hash basic types, we must write a little boilerplate code. #+CAPTION: BloomFilter/Hash.hs @@ -638,7 +638,7 @@ instance Hashable Int where hashSalt = hashStorable instance Hashable Double where hashSalt = hashStorable #+END_SRC -We might prefer to use the ~Storable~ typeclass to write just one +We might prefer to use the ~Storable~ type class to write just one declaration, as follows: #+CAPTION: BloomFilter/Hash.hs diff --git a/28-software-transactional-memory.org b/28-software-transactional-memory.org index a8e7468..db7ce9d 100644 --- a/28-software-transactional-memory.org +++ b/28-software-transactional-memory.org @@ -361,7 +361,7 @@ maybeSTM m = (Just `liftM` m) `orElse` return Nothing Secondly, we want to try an action over successive elements of a list, stopping at the first that succeeds, or performing a ~retry~ if every one fails. Conveniently for us, STM is an instance of the -~MonadPlus~ typeclass. +~MonadPlus~ type class. #+CAPTION: STMPlus.hs #+BEGIN_EXAMPLE @@ -392,7 +392,7 @@ shoppingList list buyer seller = maybeSTM . msum $ map sellOne list return this #+END_EXAMPLE -Since STM is an instance of the ~MonadPlus~ typeclass, we can +Since STM is an instance of the ~MonadPlus~ type class, we can generalize ~maybeSTM~ to work over any ~MonadPlus~. #+CAPTION: GameInventory.hs diff --git a/6-using-typeclasses.org b/6-using-typeclasses.org index b3f1788..b4bc702 100644 --- a/6-using-typeclasses.org +++ b/6-using-typeclasses.org @@ -1,13 +1,13 @@ -* Chapter 6: Using Typeclasses +* Chapter 6: Using Type Classes -Typeclasses are among the most powerful features in Haskell. They +Type classes are among the most powerful features in Haskell. They allow you to define generic interfaces that provide a common -feature set over a wide variety of types. Typeclasses are at the +feature set over a wide variety of types. Type classes are at the heart of some basic language features such as equality testing and -numeric operators. Before we talk about what exactly typeclasses +numeric operators. Before we talk about what exactly type classes are, though, we'd like to explain the need for them. -** The need for typeclasses +** The need for type classes Let's imagine that for some unfathomable reason, the designers of the Haskell language neglected to implement the equality test @@ -70,21 +70,21 @@ things, then it ought to be able to accept any data type that the compiler knows how to compare. And, what's more, if new data types are added later, the existing code shouldn't have to be modified. -Haskell's typeclasses are designed to address all of these things. +Haskell's type classes are designed to address all of these things. -** What are typeclasses? +** What are type classes? -Typeclasses define a set of functions that can have different +Type classes define a set of functions that can have different implementations depending on the type of data they are given. -Typeclasses may look like the objects of object-oriented +Type classes may look like the objects of object-oriented programming, but they are truly quite different. -Let's use typeclasses to solve our equality dilemma from earlier -in the chapter. To begin with, we must define the typeclass +Let's use type classes to solve our equality dilemma from earlier +in the chapter. To begin with, we must define the type class itself. We want a function that takes two parameters, both the same type, and returns a ~Bool~ indicating whether or not they are equal. We don't care what that type is, but we just want two items -of that type. Here's our first definition of a typeclass: +of that type. Here's our first definition of a type class: #+CAPTION: EqClasses.hs #+BEGIN_SRC haskell @@ -92,17 +92,17 @@ class BasicEq a where isEqual :: a -> a -> Bool #+END_SRC -This says that we are declaring a typeclass named ~BasicEq~, and +This says that we are declaring a type class named ~BasicEq~, and we'll refer to instance types with the letter ~a~. An instance -type of this typeclass is any type that implements the functions -defined in the typeclass. This typeclass defines one function. +type of this type class is any type that implements the functions +defined in the type class. This type class defines one function. That function takes two parameters–both corresponding to instance types–and returns a ~Bool~. #+BEGIN_NOTE When is a class not a class? -The keywoard to define a typeclass in Haskell is ~class~. +The keywoard to define a type class in Haskell is ~class~. Unfortunately, this may be confusing for those of you coming from an object-oriented background, as we are not really defining the same thing. @@ -161,10 +161,10 @@ that we could fix the problem by defining an instance of ~BasicEq~ for ~[Char]~, which is the same as ~String~. We'll go into more detail on defining instances in -[[file:6-using-typeclasses.org::*Declaring typeclass instances][the section called "Declaring typeclass instances"]] -let's continue to look at ways to define typeclasses. In this +[[file:6-using-typeclasses.org::*Declaring type class instances][the section called "Declaring type class instances"]] +let's continue to look at ways to define type classes. In this example, a not-equal-to function might be useful. Here's what we -might say to define a typeclass with two functions: +might say to define a type class with two functions: #+CAPTION: EqClasses.hs #+BEGIN_SRC haskell @@ -180,7 +180,7 @@ While our definition of ~BasicEq2~ is fine, it seems that we're making extra work for ourselves. Logically speaking, if we know what ~isEqual~ or ~isNotEqual~ would return, we know how to figure out what the other function would return, for all types. Rather -than making users of the typeclass define both functions for all +than making users of the type class define both functions for all types, we can provide default implementations for them. Then, users will only have to implement one function.[fn:1] Here's an example that shows how to do this. @@ -205,11 +205,11 @@ function must always be implemented. With ~BasicEq3~, we have provided a class that does very much the same thing as Haskell's built-in ~==~ and ~/=~ operators. In fact, -these operators are defined by a typeclass that looks almost +these operators are defined by a type class that looks almost identical to ~BasicEq3~. The Haskell 2010 Report defines a -typeclass that implements equality comparison. Here is the code -for the built-in ~Eq~ typeclass. Note how similar it is to our -~BasicEq3~ typeclass. +type class that implements equality comparison. Here is the code +for the built-in ~Eq~ type class. Note how similar it is to our +~BasicEq3~ type class. #+BEGIN_SRC haskell class Eq a where @@ -220,15 +220,15 @@ class Eq a where x == y = not (x /= y) #+END_SRC -** Declaring typeclass instances +** Declaring type class instances -Now that you know how to define typeclasses, it's time to learn -how to define instances of typeclasses. Recall that types are made -instances of a particular typeclass by implementing the functions -necessary for that typeclass. +Now that you know how to define type classes, it's time to learn +how to define instances of type classes. Recall that types are made +instances of a particular type class by implementing the functions +necessary for that type class. Recall our attempt to create a test for equality over a ~Color~ -type back in [[file:6-using-typeclasses.org::*The need for typeclasses][the section called "The need for typeclasses"]] +type back in [[file:6-using-typeclasses.org::*The need for type classes][the section called "The need for type classes"]] let's see how we could make that same ~Color~ type a member of the ~BasicEq3~ class. @@ -244,7 +244,7 @@ instance BasicEq3 Color where #+END_SRC Notice that we provide essentially the same function as we used -back in [[file:6-using-typeclasses.org::*The need for typeclasses][the section called "The need for typeclasses"]] +back in [[file:6-using-typeclasses.org::*The need for type classes][the section called "The need for type classes"]] the implementation is identical. However, in this case, we can use ~isEqual3~ on /any/ type that we declare is an instance of ~BasicEq3~, not just this one color type. We could define equality @@ -261,21 +261,21 @@ in ~BasicEq3~. Since we didn't explicitly define ~isNotEqual3~, the compiler automatically uses the default implementation given in the ~BasicEq3~ declaration. -** Important Built-In Typeclasses +** Important Built-In Type Classes -Now that we've discussed defining your own typeclasses and making -your types instances of typeclasses, it's time to introduce you to -typeclasses that are a standard part of the Haskell prelude. As we -mentioned at the beginning of this chapter, typeclasses are at the +Now that we've discussed defining your own type classes and making +your types instances of type classes, it's time to introduce you to +type classes that are a standard part of the Haskell prelude. As we +mentioned at the beginning of this chapter, type classes are at the core of some important aspects of the language. We'll cover the most common ones here. For more details, the Haskell library reference is a good resource. It will give you a description of -the typeclasses, and usually also will tell you which functions +the type classes, and usually also will tell you which functions you must implement to have a complete definition. *** Show -The ~Show~ typeclass is used to convert values to ~String~s. It is +The ~Show~ type class is used to convert values to ~String~s. It is perhaps most commonly used to convert numbers to ~String~s, but it is defined for so many types that it can be used to convert quite a bit more. If you have defined your own types, making them @@ -351,12 +351,12 @@ instance Show Color where #+END_SRC This example defines an instance of ~Show~ for our type ~Color~ -(see [[file:6-using-typeclasses.org::*The need for typeclasses][the section called "The need for typeclasses"]] +(see [[file:6-using-typeclasses.org::*The need for type classes][the section called "The need for type classes"]] implementation is simple: we define a function ~show~ and that's all that's needed. #+BEGIN_NOTE -The Show typeclass +The Show type class ~Show~ is usually used to define a ~String~ representation for data that is useful for a machine to parse back with ~Read~. @@ -367,7 +367,7 @@ representation would be different than expected via ~Show~. *** Read -The ~Read~ typeclass is essentially the opposite of ~Show~: it +The ~Read~ type class is essentially the opposite of ~Show~: it defines functions that will take a ~String~, parse it, and return data in any type that is a member of ~Read~. The most useful function in ~Read~ is ~read~. You can ask ~ghci~ for its type like @@ -506,7 +506,7 @@ leading spaces, which is common practice in Haskell programs. Read is not widely used While it is possible to build sophisticated parsers using the -~Read~ typeclass, many people find it easier to do so using +~Read~ type class, many people find it easier to do so using Parsec, and rely on ~Read~ only for simpler tasks. Parsec is covered in detail in [[file:14-using-parsec.org][Chapter 16, /Using Parsec/]]. #+END_TIP @@ -595,11 +595,11 @@ Haskell has a powerful set of numeric types. You can use everything from fast 32-bit or 64-bit integers to arbitrary-precision rational numbers. You probably know that operators such as ~+~ can work with just about all of these. This -feature is implemented using typeclasses. As a side benefit, it +feature is implemented using type classes. As a side benefit, it allows you to define your own numeric types and make them first-class citizens in Haskell. -Let's begin our discussion of the typeclasses surrounding numeric +Let's begin our discussion of the type classes surrounding numeric types with an examination of the types themselves. [[Table%C2%A06.1.%C2%A0Selected Numeric Types][Table 6.1, "Selected Numeric Types"]] describes the most commonly-used numeric types in Haskell. Note that there are also @@ -630,8 +630,8 @@ operations, such as addition, that work with all of them. There are others, such as ~asin~, that only apply to floating-point types. [[Table%C2%A06.2.%C2%A0Selected Numeric Functions and Constants][Table 6.2, "Selected Numeric Functions and Constants"]] summarizes the different functions that operate on numeric types, -and [[Table%C2%A06.3.%C2%A0Typeclass Instances for Numeric Types][Table 6.3, "Typeclass Instances for Numeric Types"]] matches the -types with their respective typeclasses. As you read that table, +and [[Table%C2%A06.3.%C2%A0Type Class Instances for Numeric Types][Table 6.3, "Type Class Instances for Numeric Types"]] matches the +types with their respective type classes. As you read that table, keep in mind that Haskell operators are just functions: you can say either ~(+) 2 3~ or ~2 + 3~ with the same result. By convention, when referring to an operator as a function, it is @@ -677,8 +677,8 @@ written in parenthesis as seen in this table. | ~truncate~ | ~(RealFrac a, Integral b) ~> a -> b~ | ~Prelude~ | Truncates number towards zero | | ~xor~ | ~Bits a ~> a -> a -> a~ | ~Data.Bits~ | Bitwise exclusive or | -#+NAME: Table 6.3. Typeclass Instances for Numeric Types -#+CAPTION: Table 6.3. Typeclass Instances for Numeric Types +#+NAME: Table 6.3. Type Class Instances for Numeric Types +#+CAPTION: Table 6.3. Type Class Instances for Numeric Types | Type | ~Bits~ | ~Bounded~ | ~Floating~ | ~Fractional~ | ~Integral~ | ~Num~ | ~Real~ | ~RealFrac~ | |---------------------------+--------+-----------+------------+--------------+------------+-------+--------+------------| | ~Double~ |   |   | X | X |   | X | X | X | @@ -714,7 +714,7 @@ on converting between different types. | ~Rational~ | ~fromRational~ | ~truncate~[fn:3] | ~truncate~[fn:3] | N/A | For an extended example demonstrating the use of these numeric -typeclasses, see +type classes, see [[file:13-data-structures.org::*Extended example: Numeric Types][the section called "Extended example: Numeric Types"]] *** Equality, Ordering, and Comparisons @@ -726,8 +726,8 @@ obvious, of course, are the equality tests: ~==~ and ~/=~. These operators are defined in the ~Eq~ class. There are also comparison operators such as ~>=~ and ~<=~. These -are declared by the ~Ord~ typeclass. These are in a separate -typeclass because there are some types, such as ~Handle~, where an +are declared by the ~Ord~ type class. These are in a separate +type class because there are some types, such as ~Handle~, where an equality test makes sense, but there is no way to express a particular ordering. Anything that is an instance of ~Ord~ can be sorted by ~Data.List.sort~. @@ -760,8 +760,8 @@ data Color = Red | Green | Blue Which types can be automatically derived? The Haskell standard requires compilers to be able to -automatically derive instances of these specific typeclasses. This -automation is not available for other typeclasses. +automatically derive instances of these specific type classes. This +automation is not available for other type classes. #+END_NOTE Let's take a look at how these derived instances work for us: @@ -794,9 +794,9 @@ will not be able to derive an instance of ~Show~ because it doesn't know how to render a function. We will get a compilation error in such a situation. -When we automatically derive an instance of some typeclass, the +When we automatically derive an instance of some type class, the types that we refer to in our ~data~ declaration must also be -instances of that typeclass (manually or automatically). +instances of that type class (manually or automatically). #+CAPTION: AutomaticDerivation.hs #+BEGIN_SRC haskell @@ -815,7 +815,7 @@ data ThisWorks = ThisWorks OK deriving (Show) #+END_SRC -** Typeclasses at work: making JSON easier to use +** Type classes at work: making JSON easier to use The ~JValue~ type that we introduced in [[file:5-writing-a-library.org::*Representing JSON data in Haskell][the section called "Representing JSON data in Haskell"]] @@ -871,7 +871,7 @@ we want to change the number ~3920~ to a string ~"3,920"~, we must change the constructor that we use to wrap it from ~JNumber~ to ~JString~. -Haskell's typeclasses offer a tempting solution to this problem. +Haskell's type classes offer a tempting solution to this problem. #+CAPTION: JSONClass.hs #+BEGIN_SRC haskell @@ -922,7 +922,7 @@ data Either a b = Left a Quite often, the type we use for the ~a~ parameter value is ~String~, so we can provide a useful description if something goes wrong. To see how we use the ~Either~ type in practice, let's look -at a simple instance of our typeclass. +at a simple instance of our type class. #+CAPTION: JSONClass.hs #+BEGIN_SRC haskell @@ -1013,8 +1013,8 @@ because it is implied by ~FlexibleInstances~. ** Living in an open world -Haskell's typeclasses are intentionally designed to let us create -new instances of a typeclass whenever we see fit. +Haskell's type classes are intentionally designed to let us create +new instances of a type class whenever we see fit. #+CAPTION: JSONClass.hs #+BEGIN_SRC haskell @@ -1036,10 +1036,10 @@ instance JSON Double where #+END_SRC We can add new instances anywhere; they are not confined to the -module where we define a typeclass. This feature of the typeclass +module where we define a type class. This feature of the type class system is referred to as its /open world assumption/. If we had a way to express a notion of "the following are the only instances -of this typeclass that can exist", we would have a /closed/ world. +of this type class that can exist", we would have a /closed/ world. We would like to be able to turn a list into what JSON calls an array. We won't worry about implementation details just yet, so @@ -1121,7 +1121,7 @@ instance (Borked a, Borked b) => Borked (a, b) where bork (a, b) = ">>" ++ bork a ++ " " ++ bork b ++ "<<" #+END_SRC -We have two instances of the typeclass ~Borked~ for pairs: one for +We have two instances of the type class ~Borked~ for pairs: one for a pair of ~Int~s and another for a pair of anything else that's ~Borked~. @@ -1137,10 +1137,10 @@ report an error if we try to use ~bork~. #+BEGIN_NOTE When do overlapping instances matter? -As we mentioned earlier, we can scatter instances of a typeclass +As we mentioned earlier, we can scatter instances of a type class across several modules. GHC does not complain about the mere existence of overlapping instances. Instead, it only complains -when we try to use a method of the affected typeclass, when it is +when we try to use a method of the affected type class, when it is forced to make a decision about which instance to use. #+END_NOTE @@ -1185,7 +1185,7 @@ specified for ~[a]~. These language extensions are specific to GHC, and by definition were not present in Haskell 2010. However, the familiar ~Show~ -typeclass from Haskell 2010 somehow renders a list of ~Char~ +type class from Haskell 2010 somehow renders a list of ~Char~ differently from a list of ~Int~. It achieves this via a clever, but simple, trick. @@ -1250,7 +1250,7 @@ identifier; we cannot see that it is implemented as an ~Int~. #+END_NOTE When we declare a ~newtype~, we must choose which of the -underlying type's typeclass instances we want to expose. Here, +underlying type's type class instances we want to expose. Here, we've elected to make ~NewtypeInt~ provide ~Int~'s instances for ~Eq~, ~Ord~ and ~Show~. As a result, we can compare and print values of type ~NewtypeInt~. @@ -1278,8 +1278,8 @@ constructor to create a new value, or to pattern match on an existing value. If a ~newtype~ does not use automatic deriving to expose the -underlying type's implementation of a typeclass, we are free to -either write a new instance or leave the typeclass unimplemented. +underlying type's implementation of a type class, we are free to +either write a new instance or leave the type class unimplemented. *** Differences between data and newtype declarations @@ -1412,14 +1412,14 @@ names for types. identity. The original type and the new type are /not/ interchangeable. -** JSON typeclasses without overlapping instances +** JSON type classes without overlapping instances Enabling GHC's support for overlapping instances is an effective and quick way to make our JSON code happy. In more complex cases, we will occasionally be faced with several equally good instances -for some typeclass, in which case overlapping instances will not +for some type class, in which case overlapping instances will not help us and we will need to put some ~newtype~ declarations into -place. To see what's involved, let's rework our JSON typeclass +place. To see what's involved, let's rework our JSON type class instances to use ~newtype~s instead of overlapping instances. Our first task, then, is to help the compiler to distinguish @@ -1525,7 +1525,7 @@ module JSONClass ) where #+END_SRC -This change doesn't affect the instances of the JSON typeclass +This change doesn't affect the instances of the JSON type class that we've already written, but we will want to write instances for our new ~JAry~ and ~JObj~ types. @@ -1687,7 +1687,7 @@ sometimes forces a declaration to be less polymorphic than we would expect. We mention the monomorphism restriction here because although it -isn't specifically related to typeclasses, they usually provide +isn't specifically related to type classes, they usually provide the circumstances in which it crops up. #+BEGIN_TIP @@ -1741,11 +1741,11 @@ language extension. ** Conclusion -In this chapter, you learned about the need for typeclasses and -how to use them. We talked about defining our own typeclasses and -then covered some of the important typeclasses that are defined in +In this chapter, you learned about the need for type classes and +how to use them. We talked about defining our own type classes and +then covered some of the important type classes that are defined in the Haskell library. Finally, we showed how to have the Haskell -compiler automatically derive instances of certain typeclasses for +compiler automatically derive instances of certain type classes for your types. ** Footnotes diff --git a/8-efficient-file-processing-regular-expressions-and-file-name-matching.org b/8-efficient-file-processing-regular-expressions-and-file-name-matching.org index 10e8ea0..546c523 100644 --- a/8-efficient-file-processing-regular-expressions-and-file-name-matching.org +++ b/8-efficient-file-processing-regular-expressions-and-file-name-matching.org @@ -336,7 +336,7 @@ libraries make heavy use of polymorphism. As a result, the type signature of the ~(=~)~ operator is difficult to understand, so we will not explain it here. -The ~=~~ operator uses typeclasses for both of its arguments, and +The ~=~~ operator uses type classes for both of its arguments, and also for its return type. The first argument (on the left of the ~=~~) is the text to match; the second (on the right) is the regular expression to match against. We can pass either a ~String~ @@ -366,10 +366,10 @@ ghci> "your right hand" =~ "(hand|foot)" :: Bool True #+END_SRC -In the bowels of the regexp libraries, there's a typeclass named +In the bowels of the regexp libraries, there's a type class named ~RegexContext~ that describes how a ~target~ type should behave; -the base library defines many instances of this typeclass for us. -The ~Bool~ type is an instance of this typeclass, so we get back a +the base library defines many instances of this type class for us. +The ~Bool~ type is an instance of this type class, so we get back a usable result. Another such instance is ~Int~, which gives us a count of the number of times the regexp matches. @@ -470,7 +470,7 @@ ghci> getAllMatches ("mondegreen" =~ pat) :: [(Int,Int)] #+END_SRC This is not a comprehensive list of built-in instances of the -~RegexContext~ typeclass. For a complete list, see the +~RegexContext~ type class. For a complete list, see the documentation for the ~Text.Regex.Base.Context~ module. This ability to make a function polymorphic in its result type is @@ -480,7 +480,7 @@ an unusual feature for a statically typed language. *** Mixing and matching string types -As we noted earlier, the ~=~~ operator uses typeclasses for its +As we noted earlier, the ~=~~ operator uses type classes for its argument types and its return type. We can use either ~String~ or strict ~ByteString~ values for both the regular expression and the text to match against. diff --git a/Makefile b/Makefile index 80b5775..17a11e3 100644 --- a/Makefile +++ b/Makefile @@ -15,3 +15,9 @@ htmlLinks: quote_marks: sed -i 's/“/"/g' *.org sed -i 's/”/"/g' *.org + +typeclass: + # First, manually check that all instances of "Typeclass" don't need to be "Type Class" + sed -i 's/Typeclass/Type class/g' *.org + sed -i 's/typeclass/type class/g' *.org + sed -i 's/6-using-type classes.org/6-using-typeclasses.org/g' *.org