diff --git a/exercises/chapter6/test/Main.purs b/exercises/chapter6/test/Main.purs index 0d8680f72..a03351571 100644 --- a/exercises/chapter6/test/Main.purs +++ b/exercises/chapter6/test/Main.purs @@ -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(..), (:)) @@ -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" diff --git a/exercises/chapter6/test/no-peeking/Solutions.purs b/exercises/chapter6/test/no-peeking/Solutions.purs index bb52b6b62..b25d3d8b6 100644 --- a/exercises/chapter6/test/no-peeking/Solutions.purs +++ b/exercises/chapter6/test/no-peeking/Solutions.purs @@ -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 @@ -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 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) +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 act (Self (Multiply m)) s = m * s diff --git a/text/chapter6.md b/text/chapter6.md index 9d769df9a..21ae6d105 100644 --- a/text/chapter6.md +++ b/text/chapter6.md @@ -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 @@ -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