Skip to content

Commit ae33aca

Browse files
Add Newtype exercise to calculate wattage. (#273)
* Add Newtype exercise to calculate wattage. * Change calculateWattage to use Amps and Volts and existing Watt newtype. * Update text/chapter5.md Co-authored-by: milesfrain <[email protected]> * Add solution to calculateWattage exercise. * Add Newtype exercise to calculate wattage. * Change calculateWattage to use Amps and Volts and existing Watt newtype. * Add solution to calculateWattage exercise. * Update text/chapter5.md Co-authored-by: milesfrain <[email protected]> * Add imports to solutions to fix CI * Directly compare wrapped values in calculateWattage test * Change MakeWatt example to MakeCoulomb. Update exercise to ask reader to define MakeWatt and to write calculateWattage. * Update solutions to include Watt newtype and fix imports. * Fix CI - must wait to import shapeBounds until solutions are reset Other misc changes: - No need for Columb Eq and Show - Construct with Watt, rather than MakeWatt Co-authored-by: milesfrain <[email protected]> Co-authored-by: Miles Frain <[email protected]>
1 parent a469c8c commit ae33aca

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

exercises/chapter5/src/ChapterExamples.purs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ current :: Amp
120120
current = calculateCurrent battery lightbulb
121121
-- ANCHOR_END: calculateCurrent
122122

123+
-- ANCHOR: Coulomb
124+
newtype Coulomb = MakeCoulomb Number
125+
-- ANCHOR_END: Coulomb
126+
123127
-- These are to enable testing. Will be explained in Ch6.
124128
derive newtype instance eqAmp :: Eq Amp
125129
derive newtype instance showAmp :: Show Amp
126-
127-
-- ANCHOR: Watt
128-
newtype Watt = MakeWatt Number
129-
-- ANCHOR_END: Watt

exercises/chapter5/test/Main.purs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Prelude hiding (gcd)
44
import Test.MySolutions
55
import Test.NoPeeking.Solutions -- Note to reader: Delete this line
66

7-
import ChapterExamples (Amp(..), current, fromString, gcd, gcdV2, isEmpty, livesInLA, lzs, partialFunction, showPerson, showPersonV2, sortPair, takeFive, toString, unknownPerson)
7+
import ChapterExamples (Amp(..), current, fromString, gcd, gcdV2, isEmpty, livesInLA, lzs, partialFunction, showPerson, showPersonV2, sortPair, takeFive, toString, unknownPerson, Volt(..))
88
import Data.Int (round)
99
import Data.Maybe (Maybe(Just, Nothing))
1010
import Data.Person (Person)
@@ -109,6 +109,11 @@ Note to reader: Delete this line to expand comment block -}
109109
$ shapeText $ Rectangle origin 1.0 1.0
110110
Assert.equal Nothing
111111
$ shapeText $ Line origin { x: 1.0, y: 1.0 }
112+
suite "Exercise Group - Newtype" do
113+
test "Exercise - calculateWattage" do
114+
Assert.equal 60.0
115+
$ let (Watt w) = calculateWattage (Amp 0.5) (Volt 120.0)
116+
in w
112117
suite "Exercise Group - Vector Graphics" do
113118
test "Exercise - area" do
114119
Assert.equal 50
@@ -171,4 +176,4 @@ runChapterExamples =
171176
Assert.equal true
172177
$ partialFunction true
173178
test "current" do
174-
Assert.equal (Amp 0.003) current
179+
Assert.equal (Amp 0.003) current

exercises/chapter5/test/no-peeking/Solutions.purs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Test.NoPeeking.Solutions where
22

33
import Prelude
44

5+
import ChapterExamples (Amp(..), Volt(..), Coulomb(..))
56
import Data.Maybe (Maybe(Just, Nothing))
67
import Data.Person (Person)
78
import Data.Picture
@@ -101,3 +102,8 @@ Your solution should edit `shapeBounds` in `Picture.purs`.
101102
shapeBounds :: ShapeExt -> Bounds
102103
shapeBounds (Clipped pic pt w h) = intersect (bounds pic) (DataP.shapeBounds (Rectangle pt w h))
103104
shapeBounds (Shape shape) = DataP.shapeBounds shape
105+
106+
newtype Watt = Watt Number
107+
108+
calculateWattage :: Amp -> Volt -> Watt
109+
calculateWattage (Amp i) (Volt v) = Watt $ i * v

text/chapter5.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,13 +449,21 @@ This design principle is perhaps better [communicated visually](https://twitter.
449449

450450
Note that the constructor of a newtype often has the same name as the newtype itself, but this is not a requirement. For example, unique names are also valid:
451451
```haskell
452-
{{#include ../exercises/chapter5/src/ChapterExamples.purs:Watt}}
452+
{{#include ../exercises/chapter5/src/ChapterExamples.purs:Coulomb}}
453453
```
454454

455-
In this case, `Watt` is the _type constructor_ and `MakeWatt` is the _data constructor_. These constructors live in different namespaces, even when the names are identical, such as with the `Volt` example. This is true for all ADTs.
455+
In this case, `Coulomb` is the _type constructor_ and `MakeCoulomb` is the _data constructor_. These constructors live in different namespaces, even when the names are identical, such as with the `Volt` example. This is true for all ADTs.
456456

457457
Another application of newtypes is to attach different _behavior_ to an existing type without changing its representation at runtime. We cover that use case in the next chapter when we discuss _type classes_.
458458

459+
## Exercises
460+
461+
1. (Easy) Use `newtype` to define a `Watt` unit for `Number` with `MakeWatt` as the data constructor, then define a `calculateWattage` function using this new `Watt` type and the above definitions `Amp` and `Volt`:
462+
```haskell
463+
calculateWattage :: Amp -> Volt -> Watt
464+
```
465+
A wattage in `Watt`s can be calculated as the product of a given current in `Amp`s and a given voltage in `Volt`s.
466+
459467
## A Library for Vector Graphics
460468

461469
Let's use the data types we have defined above to create a simple library for using vector graphics.

0 commit comments

Comments
 (0)