Skip to content

exercise with Distance, foldMap and Maybe for Section 4.3 #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/Solutions/Interfaces.idr
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,29 @@ allElems : (a -> Bool) -> List a -> Bool
allElems f = all . foldMap (MkAll . f)

-- 9

record Distance where
constructor MkDistance
meters : Double

implementation Semigroup Distance where
x <+> y = MkDistance (x.meters + y.meters)

implementation Monoid Distance where
neutral = MkDistance 0.0

square : Distance -> Distance
square x = MkDistance (x.meters * x.meters)

sqrt : Distance -> Distance
sqrt = MkDistance . sqrt . meters

euclidean : List Distance -> Maybe Distance
euclidean list = case list of
Nil => Nothing
xs => Just . sqrt . foldMap square $ xs

-- 10
record Sum a where
constructor MkSum
value : a
Expand All @@ -290,15 +313,15 @@ Num a => Semigroup (Product a) where
Num a => Monoid (Product a) where
neutral = MkProduct 1

-- 10
-- 11

sumList : Num a => List a -> a
sumList = value . foldMap MkSum

productList : Num a => List a -> a
productList = value . foldMap MkProduct

-- 12
-- 13

data Element = H | C | N | O | F

Expand All @@ -324,7 +347,7 @@ Semigroup Mass where
Monoid Mass where
neutral = 0.0

-- 13
-- 14

atomicMass : Element -> Mass
atomicMass H = 1.008
Expand Down
24 changes: 19 additions & 5 deletions src/Tutorial/Interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,21 @@ different instances for these.
allElems : (a -> Bool) -> List a -> Bool
```

9. Record wrappers `Sum` and `Product` are mainly used to hold
9. Using `foldMap` and the `Distance` type from earlier in this section, create a function

```idris
euclidean : List Distance -> Maybe Distance
```

where `euclidean` is the Euclidean distance from the origin to a
point whose Cartesian coordinates are given by a list. For example,
`euclidean [MkDistance 3.0, MkDistance 4.0, MkDistance 12.0] = Just (MkDistance 13.0)`,
i.e. the distance from the origin to the point (3, 4, 12) is 13 units. Other things to consider:

* `euclidean Nil` should return `Nothing`
* You may find it useful to create helper functions for performing mathematical operations on `Distance`s

10. Record wrappers `Sum` and `Product` are mainly used to hold
numeric types.

```idris
Expand All @@ -743,7 +757,7 @@ different instances for these.
When implementing `neutral`, remember that you can use integer
literals when working with numeric types.

10. Implement `sumList` and `productList` by using `foldMap` together
11. Implement `sumList` and `productList` by using `foldMap` together
with the wrappers from Exercise 9:

```idris
Expand All @@ -752,7 +766,7 @@ different instances for these.
productList : Num a => List a -> a
```

11. To appreciate the power and versatility of `foldMap`, after
12. To appreciate the power and versatility of `foldMap`, after
solving exercises 6 to 10 (or by loading `Solutions.Inderfaces`
in a REPL session), run the following at the REPL, which will -
in a single list traversal! - calculate the first and last
Expand All @@ -770,13 +784,13 @@ different instances for these.
natural numbers, or 0 and 255 for `Bits8`), these can even
be extended to `Monoid`.

12. In an earlier exercise, you implemented a data type representing
13. In an earlier exercise, you implemented a data type representing
chemical elements and wrote a function for calculating their
atomic masses. Define a new single field record type for
representing atomic masses, and implement interfaces
`Eq`, `Ord`, `Show`, `FromDouble`, `Semigroup`, and `Monoid` for this.

13. Use the new data type from exercise 12 to calculate the atomic
14. Use the new data type from exercise 12 to calculate the atomic
mass of an element and compute the molecular mass
of a molecule given by its formula.

Expand Down