Skip to content

Ch6 add exercise tests #78

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 1 commit into from
Apr 22, 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
18 changes: 11 additions & 7 deletions exercises/chapter6/spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
Welcome to a Spago project!
You can edit this file as you like.
-}
{ name =
"my-project"
{ name = "my-project"
, dependencies =
[ "console", "effect", "either", "psci-support", "strings", "tuples" ]
, packages =
./packages.dhall
, sources =
[ "src/**/*.purs", "test/**/*.purs" ]
[ "console"
, "effect"
, "either"
, "psci-support"
, "strings"
, "test-unit"
, "tuples"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}
11 changes: 9 additions & 2 deletions exercises/chapter6/src/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ module Main where
import Prelude

import Effect (Effect)
import Effect.Console (log)
import Effect.Class.Console (logShow)
import Data.Hashable (hash, hashEqual)

main :: Effect Unit
main = do
log "🍝"
logShow $ hash 123
logShow (hash true)
logShow (hash [1, 2, 3])
logShow (hash "testing")
logShow (hash 'a')
logShow ("foo" `hashEqual` "foo")
logShow ("foo" `hashEqual` "bar")
Comment on lines +11 to +17
Copy link
Member Author

Choose a reason for hiding this comment

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

These used to live in test/Main.purs, but relocating them here, since the original location seems best for exercise tests.

195 changes: 184 additions & 11 deletions exercises/chapter6/test/Main.purs
Original file line number Diff line number Diff line change
@@ -1,17 +1,190 @@
module Test.Main where

import Prelude

import Data.Foldable (foldMap, foldl, foldr)
import Data.Hashable (hash)
import Data.List (List(..), (:))
import Effect (Effect)
import Effect.Class.Console (logShow)
import Data.Hashable (hash, hashEqual)
import Partial.Unsafe (unsafePartial)
import Test.Solutions (Complex(..), Extended(..), Hour(..), Multiply(..), NonEmpty(..), OneMore(..), Self(..), act)
import Test.Unit (suite, test)
import Test.Unit.Assert as Assert
import Test.Unit.Main (runTest)

main :: Effect Unit
main = do
logShow (hash 123)
logShow (hash true)
logShow (hash [1, 2, 3])
logShow (hash "testing")
logShow (hash 'a')
logShow ("foo" `hashEqual` "foo")
logShow ("foo" `hashEqual` "bar")
main =
runTest do
suite "Exercise Group 1" do
suite "Exercise 1 - Show Shape" do
-- This should probably be added as an exercise to the end of chapter 5
-- with a note to revisit as first exercise in chapter 6
test "Show Shape todo"
$ Assert.equal "todo" "todo" -- (show myShape)
suite "Exercise Group 2" do
suite "Exercise 1 - Show and Eq for Complex" do
test "Show Complex"
$ Assert.equal "1.0+2.0i"
$ show
$ Complex { real: 1.0, imaginary: 2.0 }
{- Move this block comment starting point to enable more tests
Copy link
Member Author

Choose a reason for hiding this comment

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

Readers can drag this line down to enable more tests as they tackle each exercise.

test "Show Negative Complex"
$ Assert.equal "1.0-2.0i"
$ show
$ Complex { real: 1.0, imaginary: -2.0 }
test "Eq Complex"
$ Assert.equal (Complex { real: 1.0, imaginary: 2.0 })
$ Complex { real: 1.0, imaginary: 2.0 }
test "Eq Complex - not equal"
$ Assert.expectFailure "should not be equal"
$ Assert.equal (Complex { real: 5.0, imaginary: 2.0 })
$ Complex { real: 1.0, imaginary: 2.0 }
suite "Exercise Group 3" do
suite "Exercise 1 - Eq for NonEmpty" do
test "NonEmpty equals"
$ Assert.equal (NonEmpty 1 [ 2, 3 ])
$ NonEmpty 1 [ 2, 3 ]
test "NonEmpty not equals"
$ Assert.expectFailure "should not be equal"
$ Assert.equal (NonEmpty 1 [ 2, 3 ])
$ NonEmpty 2 [ 2, 3 ]
suite "Exercise 2 - Semigroup for NonEmpty" do
test "NonEmpty append"
$ Assert.equal (NonEmpty 1 [ 2, 3, 4, 5, 6 ])
$ NonEmpty 1 [ 2, 3 ]
<> NonEmpty 4 [ 5, 6 ]
suite "Exercise 3 - Functor for NonEmpty" do
test "NonEmpty append"
$ Assert.equal (NonEmpty 10 [ 20, 30 ])
$ map (_ * 10)
$ NonEmpty 1 [ 2, 3 ]
suite "Exercise 4 - Ord for Extended" do
-- Type annotation necessary to ensure there is an Ord instance for inner type (Int in this case)
test "Extended compare inf inf"
$ Assert.equal EQ
$ compare Infinite (Infinite :: Extended Int)
test "Extended compare inf 5"
$ Assert.equal GT
$ compare Infinite
$ Finite 5
test "Extended compare 5 inf"
$ Assert.equal LT
$ compare (Finite 5) Infinite
test "Extended compare 5 5"
$ Assert.equal EQ
$ compare (Finite 5)
$ Finite 5
test "Extended compare 6 5"
$ Assert.equal GT
$ compare (Finite 6)
$ Finite 5
test "Extended compare 5 6"
$ Assert.equal LT
$ compare (Finite 5)
$ Finite 6
suite "Exercise 5 - Foldable for NonEmpty" do
test "NonEmpty foldl"
$ Assert.equal 123
$ foldl (\acc x -> acc * 10 + x) 0
$ NonEmpty 1 [ 2, 3 ]
test "NonEmpty foldr"
$ Assert.equal 321
$ foldr (\x acc -> acc * 10 + x) 0
$ NonEmpty 1 [ 2, 3 ]
test "NonEmpty foldMap"
$ Assert.equal "123"
$ foldMap (\x -> show x)
$ NonEmpty 1 [ 2, 3 ]
suite "Exercise 6 - Foldable for OneMore" do
test "OneMore foldl"
$ Assert.equal 123
$ foldl (\acc x -> acc * 10 + x) 0
$ OneMore 1 (2 : 3 : Nil)
test "OneMore foldr"
$ Assert.equal 321
$ foldr (\x acc -> acc * 10 + x) 0
$ OneMore 1 (2 : 3 : Nil)
test "OneMore foldMap"
$ Assert.equal "123"
$ foldMap (\x -> show x)
$ OneMore 1 (2 : 3 : Nil)
suite "Exercise Group 4" do
suite "Exercise 1 - Partial maximum" do
test "unsafeMaximum"
$ Assert.equal 42
$ unsafePartial
$ unsafeMaximum [ 1, 2, 42, 3 ]
let
m1 = Multiply 3

m2 = Multiply 4
suite "Exercise 2 - Action Class" do
-- Getting Multiply Int to work is a warm-up
suite "Multiply Int" do
let
a = 5
test "Multiply Int mempty"
$ Assert.equal a
$ act (mempty :: Multiply) a
test "Multiply Int append"
$ Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
-- Multiply String is the actual exercise question
suite "Multiply String" do
let
a = "foo"
test "Multiply String mempty"
$ Assert.equal a
$ act (mempty :: Multiply) a
test "Multiply String append"
$ Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
suite "Exercise 3 - Action Array" do
suite "Multiply Array Int" do
let
a = [ 1, 2, 3 ]
test "Multiply Array Int mempty"
$ Assert.equal a
$ act (mempty :: Multiply) a
test "Multiply Arary Int append"
$ Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
suite "Multiply Array String" do
let
a = [ "foo", "bar", "baz" ]
test "Multiply Array String mempty"
$ Assert.equal a
$ act (mempty :: Multiply) a
test "Multiply Array String append"
$ Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
suite "Exercise 4 - Action Self" do
let
a = Self m1
test "Multiply Self mempty"
$ Assert.equal a
$ act (mempty :: Multiply) a
test "Multiply Self append"
$ Assert.equal (act m1 (act m2 a))
$ act (m1 <> m2) a
suite "Exercise Group 5" do
suite "Exercise 2 - Array Duplicates" do
test "No dupe"
$ Assert.equal false
$ arrayHasDuplicates [ 1, 2, 3 ]
test "Dupe"
$ Assert.equal true
$ arrayHasDuplicates [ 1, 1, 3 ]
test "Only hash dupe"
$ Assert.equal false
$ arrayHasDuplicates [ 65536, 1, 2, 3 ]
suite "Exercise 3 - Hash Hour" do
test "Match"
$ Assert.equal (hash $ Hour 1)
$ hash
$ Hour 13
test "Mismatch"
$ Assert.expectFailure "should not be equal"
$ Assert.equal (hash $ Hour 1)
$ hash
$ Hour 14
-}
49 changes: 49 additions & 0 deletions exercises/chapter6/test/Solutions.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Test.Solutions 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.

Specifying the file for solutions will enable easier comparison of solutions, similar to what's available in exercism.io


import Prelude

newtype Complex
= Complex
{ real :: Number
, imaginary :: Number
}
Comment on lines +5 to +9
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 file contains code snippets directly from the chapter text for users to complete.


data NonEmpty a
= NonEmpty a (Array a)

data Extended a
= Finite a
| Infinite

data OneMore f a
= OneMore a (f a)

-- instance foldableOneMore :: Foldable f => Foldable (OneMore f) where
-- todo
-- unsafeMaximum :: Partial => Array Int -> Int
-- todo
class
Monoid m <= Action m a where
act :: m -> a -> a

newtype Multiply
= Multiply Int

instance semigroupMultiply :: Semigroup Multiply where
append (Multiply n) (Multiply m) = Multiply (n * m)

instance monoidMultiply :: Monoid Multiply where
mempty = Multiply 1

-- instance repeatAction :: Action Multiply String where
-- todo
-- instance actionArray :: Action m a => Action m (Array a) where
-- todo
newtype Self m
= Self m

newtype Hour
= Hour Int

instance eqHour :: Eq Hour where
eq (Hour n) (Hour m) = mod n 12 == mod m 12