mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
new Set 5a Ex 12, improve tests Set 6 Ex 7, renumber Set 4
This commit is contained in:
+34
-33
@@ -38,37 +38,7 @@ myMaximum (x:xs) = foldr maxHelper x xs
|
||||
maxHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 3: get the first element of a list with a fold. Define
|
||||
-- headHelper so that the given definition of myHead works.
|
||||
--
|
||||
-- Start by giving headHelper a type.
|
||||
--
|
||||
-- Examples:
|
||||
-- myHead [] ==> Nothing
|
||||
-- myHead [1,2,3] ==> Just 1
|
||||
|
||||
myHead :: [a] -> Maybe a
|
||||
myHead xs = foldr headHelper Nothing xs
|
||||
|
||||
headHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 4: get the last element of a list with a fold. Define lasthelper
|
||||
-- so that the given definition of myLast works.
|
||||
--
|
||||
-- Start by giving lastHelper a type.
|
||||
--
|
||||
-- Examples:
|
||||
-- myLast [] ==> Nothing
|
||||
-- myLast [1,2,3] ==> Just 3
|
||||
|
||||
myLast :: [a] -> Maybe a
|
||||
myLast xs = foldr lastHelper Nothing xs
|
||||
|
||||
lastHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 5: compute the sum and length of a list with a fold. Define
|
||||
-- Ex 3: compute the sum and length of a list with a fold. Define
|
||||
-- slHelper and slStart so that the given definition of sumAndLength
|
||||
-- works. This could be used to compute the average of a list.
|
||||
--
|
||||
@@ -86,7 +56,7 @@ slStart = todo
|
||||
slHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 6: implement concat with with a fold. Define concatHelper and
|
||||
-- Ex 4: implement concat with with a fold. Define concatHelper and
|
||||
-- concatStart so that the given definition of myConcat joins inner lists
|
||||
-- of a list.
|
||||
--
|
||||
@@ -101,7 +71,7 @@ concatStart = todo
|
||||
concatHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 7: get all occurrences of the largest number in a list with a
|
||||
-- Ex 5: get all occurrences of the largest number in a list with a
|
||||
-- fold. Implement largestHelper so that the given definition of largest works.
|
||||
--
|
||||
-- Examples:
|
||||
@@ -114,3 +84,34 @@ largest xs = foldr largestHelper [] xs
|
||||
|
||||
largestHelper = todo
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 6: get the first element of a list with a fold. Define
|
||||
-- headHelper so that the given definition of myHead works.
|
||||
--
|
||||
-- Start by giving headHelper a type.
|
||||
--
|
||||
-- Examples:
|
||||
-- myHead [] ==> Nothing
|
||||
-- myHead [1,2,3] ==> Just 1
|
||||
|
||||
myHead :: [a] -> Maybe a
|
||||
myHead xs = foldr headHelper Nothing xs
|
||||
|
||||
headHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 7: get the last element of a list with a fold. Define lasthelper
|
||||
-- so that the given definition of myLast works.
|
||||
--
|
||||
-- Start by giving lastHelper a type.
|
||||
--
|
||||
-- Examples:
|
||||
-- myLast [] ==> Nothing
|
||||
-- myLast [1,2,3] ==> Just 3
|
||||
|
||||
myLast :: [a] -> Maybe a
|
||||
myLast xs = foldr lastHelper Nothing xs
|
||||
|
||||
lastHelper = todo
|
||||
|
||||
|
||||
+25
-24
@@ -15,11 +15,11 @@ main = score tests
|
||||
|
||||
tests = [(1,"countNothings",[ex1_countNothings])
|
||||
,(2,"myMaximum",[ex2_myMaximum])
|
||||
,(3,"myHead",[ex3_myHead_empty, ex3_myHead_full])
|
||||
,(4,"myLast",[ex4_myLast_empty, ex4_myLast_full])
|
||||
,(5,"sumAndLength",[ex5_sumAndLength])
|
||||
,(6,"myConcat",[ex6_myConcat])
|
||||
,(7,"largest",[ex7_largest])]
|
||||
,(3,"sumAndLength",[ex3_sumAndLength])
|
||||
,(4,"myConcat",[ex4_myConcat])
|
||||
,(5,"largest",[ex5_largest])
|
||||
,(6,"myHead",[ex6_myHead_empty, ex6_myHead_full])
|
||||
,(7,"myLast",[ex7_myLast_empty, ex7_myLast_full])]
|
||||
|
||||
ex1_countNothings = property $ do
|
||||
justs <- fmap (map Just) $ listOf (choose (0::Int,10))
|
||||
@@ -37,35 +37,36 @@ ex2_myMaximum = property $ do
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr maxHelper x xs|]) (?==maximum (x:xs))
|
||||
|
||||
ex3_myHead_empty =
|
||||
$(testing' [|foldr headHelper Nothing []|]) (?==(Nothing::Maybe Bool))
|
||||
|
||||
ex3_myHead_full =
|
||||
forAll_ $ \(NonEmpty xs::NonEmptyList Int) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr headHelper Nothing xs|]) (?==Just (head xs))
|
||||
|
||||
ex4_myLast_empty =
|
||||
$(testing' [|foldr lastHelper Nothing []|]) (?==(Nothing::Maybe Bool))
|
||||
|
||||
ex4_myLast_full =
|
||||
forAll_ $ \(NonEmpty xs::NonEmptyList Int) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr lastHelper Nothing xs|]) (?==Just (last xs))
|
||||
|
||||
niceDouble = fmap ((/2).fromIntegral) (arbitrary :: Gen Int)
|
||||
|
||||
ex5_sumAndLength =
|
||||
ex3_sumAndLength =
|
||||
forAllBlind (listOf niceDouble) $ \(ds::[Double]) ->
|
||||
counterexample ("ds = "++show ds) $
|
||||
$(testing' [|foldr slHelper slStart ds|]) (?==(sum ds, length ds))
|
||||
|
||||
ex6_myConcat =
|
||||
ex4_myConcat =
|
||||
forAll_ $ \(xs :: [[Int]]) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr concatHelper concatStart xs|]) (?==concat xs)
|
||||
|
||||
ex7_largest =
|
||||
ex5_largest =
|
||||
forAll_ $ \(NonEmpty (xs :: [Int])) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr largestHelper [] xs|]) (?==filter (==maximum xs) xs)
|
||||
|
||||
|
||||
ex6_myHead_empty =
|
||||
$(testing' [|foldr headHelper Nothing []|]) (?==(Nothing::Maybe Bool))
|
||||
|
||||
ex6_myHead_full =
|
||||
forAll_ $ \(NonEmpty xs::NonEmptyList Int) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr headHelper Nothing xs|]) (?==Just (head xs))
|
||||
|
||||
ex7_myLast_empty =
|
||||
$(testing' [|foldr lastHelper Nothing []|]) (?==(Nothing::Maybe Bool))
|
||||
|
||||
ex7_myLast_full =
|
||||
forAll_ $ \(NonEmpty xs::NonEmptyList Int) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr lastHelper Nothing xs|]) (?==Just (last xs))
|
||||
|
||||
@@ -258,3 +258,65 @@ fromNat n = todo
|
||||
toNat :: Int -> Maybe Nat
|
||||
toNat z = todo
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 12: While pleasingly simple in its definition, the Nat datatype is not
|
||||
-- very efficient computationally. Instead of the unary Peano natural numbers,
|
||||
-- computers use binary numbers.
|
||||
--
|
||||
-- Binary numbers are like decimal numbers, except that binary numbers have
|
||||
-- only two digits (called bits), 0 and 1. The table below gives some
|
||||
-- examples:
|
||||
--
|
||||
-- decimal | binary
|
||||
-- ----------------
|
||||
-- 0 | 0
|
||||
-- 1 | 1
|
||||
-- 2 | 10
|
||||
-- 7 | 111
|
||||
-- 44 | 101100
|
||||
--
|
||||
-- For allowing arbitrarily long binary numbers, our representation, the
|
||||
-- datatype Bin, includes a special End constructor for denoting the end of
|
||||
-- the binary number. In order to make computation with Bin easier, the bits
|
||||
-- are represented in increasing order by significance (i.e. "backwards").
|
||||
-- Consider the Bin numbers O (I (I End)), representing 110 in binary or
|
||||
-- 6 in decimal, and I (I (O End)) that represents 011 in binary or 3 in
|
||||
-- decimal. The most significant (last) bit, the bit I, of O (I (I End)) is
|
||||
-- greater than the bit O, which is the most significant bit of I (I (O End)).
|
||||
-- Therefore, O (I (I End)) is greater than I (I (O End)).
|
||||
--
|
||||
-- Your task is to write functions prettyPrint, fromBin, and toBin that
|
||||
-- convert Bin to human-readable string, Bin to Int, and Int to Bin
|
||||
-- respectively.
|
||||
--
|
||||
-- Examples:
|
||||
-- prettyPrint End ==> ""
|
||||
-- prettyPrint (O End) ==> "0"
|
||||
-- prettyPrint (I End) ==> "1"
|
||||
-- prettyPrint (O (O (I (O (I End))))) ==> "10100"
|
||||
-- map fromBinary [O End, I End, O (I End), I (I End), O (O (I End)),
|
||||
-- I (O (I End))]
|
||||
-- ==> [0, 1, 2, 3, 4, 5]
|
||||
-- fromBinary (I (I (O (O (I (O (I (O End)))))))) ==> 83
|
||||
-- fromBinary (I (I (O (O (I (O (I End))))))) ==> 83
|
||||
-- map toBinary [0..5] ==>
|
||||
-- [O End,I End,O (I End),I (I End),O (O (I End)),I (O (I End))]
|
||||
-- toBinary 57 ==> I (O (O (I (I (I End)))))
|
||||
--
|
||||
data Bin = End | O Bin | I Bin
|
||||
|
||||
-- This function increments a binary number by one.
|
||||
inc :: Bin -> Bin
|
||||
inc End = I End
|
||||
inc (O b) = I b
|
||||
inc (I b) = O (inc b)
|
||||
|
||||
prettyPrint :: Bin -> String
|
||||
prettyPrint = todo
|
||||
|
||||
fromBin :: Bin -> Int
|
||||
fromBin = todo
|
||||
|
||||
toBin :: Int -> Bin
|
||||
toBin = todo
|
||||
|
||||
@@ -23,6 +23,10 @@ tests = [(1,"Vehicle",[ex1])
|
||||
,(9,"OneOrTwo",[ex9])
|
||||
,(10,"KeyVals",[ex10_type, ex10_string_bool, ex10_int_int])
|
||||
,(11,"Nat",[ex11_to, ex11_from, ex11_just, ex11_nothing])
|
||||
,(12,"Bin",[ex12_from_zero, ex12_to_zero, ex12_to_from_zero
|
||||
, ex12_from_to_zero, ex12_from_one, ex12_to_one
|
||||
, ex12_to_from_one, ex12_from_to_one, ex12_to_from
|
||||
, ex12_from_to])
|
||||
]
|
||||
|
||||
-- -- -- -- -- -- -- --
|
||||
@@ -185,3 +189,29 @@ ex11_just = forAll_ $ \(n :: Nat) ->
|
||||
(toNat (fromNat n) ?== Just n)
|
||||
ex11_nothing = forAll_ $ \(Negative (z :: Int)) ->
|
||||
$(testing [|toNat z|]) (?== Nothing)
|
||||
|
||||
instance Arbitrary Bin where
|
||||
arbitrary = do
|
||||
bs <- arbitrary :: Gen [Bool]
|
||||
return $ foldr (\x b -> if x then I b else O b) (I End) (take 8 bs)
|
||||
|
||||
ex12_from_zero =
|
||||
counterexample ("fromBin (O End)") (fromBin (O End) ?== 0)
|
||||
ex12_to_zero =
|
||||
counterexample ("toBin 0") (toBin 0 ?== O End)
|
||||
ex12_to_from_zero =
|
||||
counterexample ("toBin (fromBin (O End))") (toBin (fromBin (O End)) ?== O End)
|
||||
ex12_from_to_zero =
|
||||
counterexample ("fromBin (toBin 0)") (fromBin (toBin 0) ?== 0)
|
||||
ex12_from_one =
|
||||
counterexample ("fromBin (I End)") (fromBin (I End) ?== 1)
|
||||
ex12_to_one =
|
||||
counterexample ("toBin 0") (toBin 1 ?== I End)
|
||||
ex12_to_from_one =
|
||||
counterexample ("toBin (fromBin (I End))") (toBin (fromBin (I End)) ?== I End)
|
||||
ex12_from_to_one =
|
||||
counterexample ("fromBin (toBin 1)") (fromBin (toBin 1) ?== 1)
|
||||
ex12_to_from = forAll_ $ \(b :: Bin) ->
|
||||
counterexample ("toBin (fromBin (" ++ show b ++ "))") (toBin (fromBin b) ?== b)
|
||||
ex12_from_to = forAll_ $ \(n :: Int) -> n < 0 .||.
|
||||
counterexample ("fromBin (toBin (" ++ show n ++ "))") (fromBin (toBin n) ?== n)
|
||||
|
||||
+36
-1
@@ -86,6 +86,11 @@ ex6_milk =
|
||||
conjoin [$(testing [|price [Just (Milk milk1), Nothing, Just (Milk milk2)]|]) (?==(15*milk1+15*milk2))
|
||||
,$(testing [|price [Nothing, Nothing, Nothing :: Maybe Milk]|]) (?==0)]
|
||||
|
||||
instance Arbitrary Number where
|
||||
arbitrary = do
|
||||
b <- arbitrary
|
||||
if b then arbitrary >>= return . Finite else return Infinite
|
||||
|
||||
ex7_eq_check =
|
||||
$(withInstance "Eq" "Number" [|(==) :: Number -> Number -> Bool|]) $ \(==) ->
|
||||
forAll_ $ \i ->
|
||||
@@ -94,6 +99,34 @@ ex7_eq_check =
|
||||
,$(testing [|Finite i == Infinite|]) (?==False)
|
||||
,$(testing [|Infinite == Infinite|]) (?==True)]
|
||||
|
||||
ex7_trichotomy =
|
||||
$(withInstance "Eq" "Number" [|(==) :: Number -> Number -> Bool|]) $ \(==) ->
|
||||
forAll_ $ \(x :: Number) ->
|
||||
forAll_ $ \(y :: Number) ->
|
||||
(x /= y) ==> counterexample
|
||||
(show x ++ " /= " ++ show y ++ ", but neither " ++
|
||||
show x ++ " < " ++ show y ++ " or " ++
|
||||
show x ++ " > " ++ show y ++ " was true")
|
||||
(x < y || x > y)
|
||||
|
||||
ex7_reflexivity =
|
||||
$(withInstance "Eq" "Number" [|(==) :: Number -> Number -> Bool|]) $ \(==) ->
|
||||
forAll_ $ \(x :: Number) ->
|
||||
$(testing [| x <= x |]) (?==True)
|
||||
|
||||
ex7_antisymmetry =
|
||||
$(withInstance "Eq" "Number" [|(==) :: Number -> Number -> Bool|]) $ \(==) ->
|
||||
forAll_ $ \(x :: Number) ->
|
||||
forAll_ $ \(y :: Number) ->
|
||||
(x <= y && y <= x) ==> $(testing [| x == y |]) (?==True)
|
||||
|
||||
ex7_transitivity =
|
||||
$(withInstance "Eq" "Number" [|(==) :: Number -> Number -> Bool|]) $ \(==) ->
|
||||
forAll_ $ \(x :: Number) ->
|
||||
forAll_ $ \(y :: Number) ->
|
||||
forAll_ $ \(z :: Number) ->
|
||||
(x <= y && y <= z) ==> $(testing [| x <= z |]) (?==True)
|
||||
|
||||
ex7_finite =
|
||||
$(withInstance "Ord" "Number" [|max :: Number -> Number -> Number|]) $ \max ->
|
||||
forAll_ $ \i ->
|
||||
@@ -273,7 +306,9 @@ tests = [(1,"Eq Country",[ex1])
|
||||
,(4,"Eq List",[ex4_eq, ex4_neq])
|
||||
,(5,"Price",[ex5_egg, ex5_milk])
|
||||
,(6,"Price List",[ex6_egg, ex6_milk])
|
||||
,(7,"Ord Number",[ex7_eq_check, ex7_finite, ex7_infinite])
|
||||
,(7,"Ord Number",[ ex7_eq_check, ex7_trichotomy, ex7_reflexivity
|
||||
, ex7_antisymmetry, ex7_transitivity, ex7_finite
|
||||
, ex7_infinite ])
|
||||
,(8,"Eq RationalNumber",[ex8_refl, ex8_eq])
|
||||
,(9,"simplify",[ex9_prime, ex9_eq])
|
||||
,(10,"Num RationalNumber",[ex10_add_zero, ex10_add_commut, ex10_add_whole, ex10_add
|
||||
|
||||
@@ -3392,6 +3392,7 @@ If I define an instance for <code>Num</code>, I also get an instance for <code>F
|
||||
<p>By the way, these functions are available as <code>Data.List.NonEmpty.head</code> and <code>Data.List.NonEmpty.last</code> along with many other useful functions.</p>
|
||||
<p>In summary, if you write types that represent all possible cases for your values, and then write functions that handle those cases, your code will be simple and correct.</p>
|
||||
<h2 id="monoids"><span class="header-section-number">7.3</span> Monoids</h2>
|
||||
<!-- TODO: Give an example of a semigroup that is not a monoid. -->
|
||||
<!-- TODO: move to the end of the lecture? -->
|
||||
<h3 id="what"><span class="header-section-number">7.3.1</span> What?</h3>
|
||||
<p>A simple but useful abstraction that Haskell libraries use is that of the <em>monoid</em>. (Not to be confused with a <em>monad</em>!) In Haskell terms, <code>Monoid</code> is a type class that contains the function <code><></code> and the constant <code>mempty</code>.</p>
|
||||
|
||||
Reference in New Issue
Block a user