Skip to content

Ch6 - Clarify Action exercises #228

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

Merged
merged 2 commits into from
Nov 11, 2020
Merged
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
4 changes: 3 additions & 1 deletion exercises/chapter6/test/Main.purs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module Test.Main where

import Prelude
import Test.MySolutions
import Test.NoPeeking.Solutions -- Note to reader: Delete this line

import Data.Foldable (foldMap, foldl, foldr)
import Data.Hashable (hash)
import Data.List (List(..), (:))
Expand Down Expand Up @@ -166,7 +168,7 @@ Note to reader: Delete this line to expand comment block -}
Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
test "Multiply Array String append concrete" do
Assert.equal
Assert.equal
[ "foofoofoofoofoofoofoofoofoofoofoofoo"
, "barbarbarbarbarbarbarbarbarbarbarbar"
, "bazbazbazbazbazbazbazbazbazbazbazbaz"
Expand Down
31 changes: 10 additions & 21 deletions exercises/chapter6/test/no-peeking/Solutions.purs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,14 @@ instance semigroupMultiply :: Semigroup Multiply where
instance monoidMultiply :: Monoid Multiply where
mempty = Multiply 1

instance actionMultiply :: Action Multiply Int where
instance actionMultiplyInt :: Action Multiply Int where
act (Multiply n) m = n * m

instance showMultiply :: Show Multiply where
show (Multiply n) = "Multiply " <> show n
-- These may also be written manualy
derive newtype instance showMultiply :: Show Multiply
derive newtype instance eqMultiply :: Eq Multiply

instance eqMultiply :: Eq Multiply where
eq (Multiply n) (Multiply m) = n == m

instance repeatAction :: Action Multiply String where
instance actionMultiplyString :: Action Multiply String where
act (Multiply n) s = power s n

instance actionArray :: Action m a => Action m (Array a) where
Expand All @@ -107,23 +105,14 @@ instance actionArray :: Action m a => Action m (Array a) where
newtype Self m
= Self m

-- Why is Monoid constraint required here?
-- Seems like this is already specified by Action class
--instance actionSelf :: Action m (Self m) where
instance actionSelf :: Monoid m => Action m (Self m) where
Copy link
Member Author

@milesfrain milesfrain Nov 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the Monoid constraint required here? It seems like this superclass relationship is already specified by the Action class and that it should be possible to write it like this instead:

instance actionSelf :: Action m (Self m) where

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer:

it's required for the superclass relationship, it's not provided by the superclass relationship

act m1 (Self m2) = Self (m1 <> m2)

instance eqSelf :: Eq m => Eq (Self m) where
eq (Self m1) (Self m2) = m1 == m2

instance showSelf :: Show m => Show (Self m) where
show (Self m) = "Self " <> show m

instance semigroupSelf :: Semigroup m => Semigroup (Self m) where
append (Self a) (Self b) = Self (a <> b)

instance monoidSelf :: Monoid m => Monoid (Self m) where
mempty = Self mempty
-- These may also be written manualy
derive newtype instance showSelf :: Show m => Show (Self m)
derive newtype instance eqSelf :: Eq m => Eq (Self m)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fine to write without newtype wrapper:

derive instance eqSelf :: Eq m => Eq (Self m)

derive newtype instance semigroupSelf :: Semigroup m => Semigroup (Self m)
derive newtype instance monoidSelf :: Monoid m => Monoid (Self m)

instance repeatActionMultSelf :: Action (Self Multiply) Int where
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not be the best instance name (doesn't follow the earlier convention of just squishing everything together), although this doesn't really matter.

act (Self (Multiply m)) s = m * s
Expand Down
19 changes: 16 additions & 3 deletions text/chapter6.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ Another reason to define a superclass relationship is in the case where there is
## Exercises

1. (Medium) Define a partial function `unsafeMaximum :: Partial => Array Int -> Int` which finds the maximum of a non-empty array of integers. Test out your function in PSCi using `unsafePartial`. _Hint_: Use the `maximum` function from `Data.Foldable`.

1. (Medium) The `Action` class is a multi-parameter type class which defines an action of one type on another:

```haskell
Expand All @@ -661,20 +662,32 @@ Another reason to define a superclass relationship is in the case where there is
mempty = Multiply 1
```

This monoid acts on strings by repeating an input string some number of times. Write an instance which implements this action:
Write an instance which implements this action:

```haskell
instance actionMultiplyInt :: Action Multiply Int
```
Does this instance satisfy the laws listed above?

1. (Medium) Write an `Action` instance which repeats an input string some number of times:

```haskell
instance repeatAction :: Action Multiply String
instance actionMultiplyString :: Action Multiply String
```
_Hint_: Search Pursuit for a helper-function with the signature `String -> Int -> String`. Note that `String` might appear as a more generic type.
_Hint_: Search Pursuit for a helper-function with the signature [`String -> Int -> String`](https://pursuit.purescript.org/search?q=String%20-%3E%20Int%20-%3E%20String). Note that `String` might appear as a more generic type (such as `Monoid`).

Does this instance satisfy the laws listed above?

1. (Medium) Write an instance `Action m a => Action m (Array a)`, where the action on arrays is defined by acting on each array element independently.

1. (Difficult) Given the following newtype, write an instance for `Action m (Self m)`, where the monoid `m` acts on itself using `append`:

```haskell
newtype Self m = Self m
```

_Note_: The testing framework requires `Show` and `Eq` instances for the `Self` and `Multiply` types. You may either write these instances manually, or let the compiler handle this for you with [`derive newtype instance`](https://github.com/purescript/documentation/blob/master/language/Type-Classes.md#derive-from-newtype) shorthand.

1. (Difficult) Should the arguments of the multi-parameter type class `Action` be related by some functional dependency? Why or why not? _Note_: There is no test for this exercise.

## A Type Class for Hashes
Expand Down