mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
add Set4a, Set4b
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
-- Exercise set 4a:
|
||||
--
|
||||
-- * using type classes
|
||||
-- * working with lists
|
||||
--
|
||||
-- Type classes you'll need
|
||||
-- * Eq
|
||||
-- * Ord
|
||||
-- * Num
|
||||
-- * Fractional
|
||||
--
|
||||
-- Useful functions:
|
||||
-- * maximum
|
||||
-- * minimum
|
||||
-- * sort
|
||||
|
||||
|
||||
module Set4a where
|
||||
|
||||
import Mooc.Todo
|
||||
import Data.List
|
||||
import Data.Ord
|
||||
import qualified Data.Map as Map
|
||||
import Data.Array
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 1: implement the function allEqual which returns True if all
|
||||
-- values in the list are equal.
|
||||
--
|
||||
-- Examples:
|
||||
-- allEqual [] ==> True
|
||||
-- allEqual [1,2,3] ==> False
|
||||
-- allEqual [1,1,1] ==> True
|
||||
--
|
||||
-- PS. check out the error message you get with your implementation if
|
||||
-- you remove the Eq a => constraint from the type!
|
||||
|
||||
allEqual :: Eq a => [a] -> Bool
|
||||
allEqual xs = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 2: implement the function distinct which returns True if all
|
||||
-- values in a list are different.
|
||||
--
|
||||
-- Hint: a certain function from the lecture material can make this
|
||||
-- really easy for you.
|
||||
--
|
||||
-- Examples:
|
||||
-- distinct [] ==> True
|
||||
-- distinct [1,1,2] ==> False
|
||||
-- distinct [1,2] ==> True
|
||||
|
||||
distinct :: Eq a => [a] -> Bool
|
||||
distinct = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 3: implement the function middle that returns the middle value
|
||||
-- (not the smallest or the largest) out of its three arguments.
|
||||
--
|
||||
-- The function should work on all types in the Ord class. Give it a
|
||||
-- suitable type signature.
|
||||
--
|
||||
-- Examples:
|
||||
-- middle 'b' 'a' 'c' ==> 'b'
|
||||
-- middle 1 7 3 ==> 3
|
||||
|
||||
middle = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 4: return the range of an input list, that is, the difference
|
||||
-- between the smallest and the largest element.
|
||||
--
|
||||
-- Your function should work on all suitable types, like Float and
|
||||
-- Int. You'll need to add _class constraints_ to the type of range.
|
||||
--
|
||||
-- It's fine if your function doesn't work for empty inputs.
|
||||
--
|
||||
-- Examples:
|
||||
-- rangeOf [4,2,1,3] ==> 3
|
||||
-- rangeOf [1.5,1.0,1.1,1.2] ==> 0.5
|
||||
|
||||
rangeOf :: [a] -> a
|
||||
rangeOf = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 5: given a list of lists, return the longest lists. If there
|
||||
-- are multiple lists of the same length, return the string that has
|
||||
-- the smallest _first element_.
|
||||
--
|
||||
-- (If multiple lists have the same length and same first element,
|
||||
-- you can return any one of them.)
|
||||
--
|
||||
-- Give the longest function a suitable type.
|
||||
--
|
||||
-- Examples:
|
||||
-- longest [[1,2,3],[4,5],[6]] ==> [1,2,3]
|
||||
-- longest ["abc","def","axx"] ==> "def"
|
||||
|
||||
longest = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 6: Implement the function incrementKey, that takes a list of
|
||||
-- (key,value) pairs, and adds 1 to all the values that have the given key.
|
||||
--
|
||||
-- You'll need to add _class constraints_ to the type of incrementKey
|
||||
-- to make the function work!
|
||||
--
|
||||
-- The function needs to be generic and handle all compatible types,
|
||||
-- see the examples.
|
||||
--
|
||||
-- Examples:
|
||||
-- incrementKey True [(True,1),(False,3),(True,4)] ==> [(True,2),(False,3),(True,5)]
|
||||
-- incrementKey 'a' [('a',3.4)] ==> [('a',4.4)]
|
||||
|
||||
incrementKey :: k -> [(k,v)] -> [(k,v)]
|
||||
incrementKey = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 7: compute the average of a list of values of the Fractional
|
||||
-- class.
|
||||
--
|
||||
-- There is no need to handle the empty list case.
|
||||
--
|
||||
-- Hint! since Fractional is a subclass of Num, you have all
|
||||
-- arithmetic operations available
|
||||
--
|
||||
-- Hint! you can use the function fromIntegral to convert the list
|
||||
-- length to a Fractional
|
||||
|
||||
average :: Fractional a => [a] -> a
|
||||
average xs = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 8: given a map from player name to score and two players, return
|
||||
-- the name of the player with more points. If the players are tied,
|
||||
-- return the name of the first player.
|
||||
--
|
||||
-- If a player doesn't exist in the map, you can assume they have 0 points.
|
||||
--
|
||||
-- Hint: Map.findWithDefault can make this simpler
|
||||
--
|
||||
-- Examples:
|
||||
-- winner (fromList [("Bob",3470),("Jane",2130),("Lisa",9448)]) "Jane" "Lisa"
|
||||
-- ==> "Lisa"
|
||||
-- winner (Map.fromList [("Bob",5899),("Lisa",5899),("Mike",13607)]) "Bob" "Lisa"
|
||||
-- ==> "Bob"
|
||||
|
||||
winner :: Map.Map String Int -> String -> String -> String
|
||||
winner scores player1 player2 = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 9: compute how many times each value in the list occurs. Return
|
||||
-- the frequencies as a Map from value to Int.
|
||||
--
|
||||
-- Challenge 1: try using Map.alter for this
|
||||
--
|
||||
-- Challenge 2: use foldr to process the list
|
||||
--
|
||||
-- Example:
|
||||
-- freqs [False,False,False,True]
|
||||
-- ==> Map.fromList [(False,3),(True,1)]
|
||||
|
||||
freqs :: (Eq a, Ord a) => [a] -> Map.Map a Int
|
||||
freqs xs = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 10: recall the withdraw example from the course material. Write a
|
||||
-- similar function, transfer, that transfers money from one account
|
||||
-- to another.
|
||||
--
|
||||
-- However, the function should not perform the transfer if
|
||||
-- * the from account doesn't exist,
|
||||
-- * the to account doesn't exist
|
||||
-- * or the from account doesn't have enough money.
|
||||
--
|
||||
-- Hint: there are many ways to implement this logic. Map.member or
|
||||
-- Map.notMember might help.
|
||||
--
|
||||
-- Examples:
|
||||
-- let bank = Map.fromList [("Bob",100),("Mike",50)]
|
||||
-- transfer "Bob" "Mike" 20 bank
|
||||
-- ==> fromList [("Bob",80),("Mike",70)]
|
||||
-- transfer "Bob" "Mike" 120 bank
|
||||
-- ==> fromList [("Bob",100),("Mike",50)]
|
||||
-- transfer "Bob" "Lisa" 20 bank
|
||||
-- ==> fromList [("Bob",100),("Mike",50)]
|
||||
-- transfer "Lisa" "Mike" 20 bank
|
||||
-- ==> fromList [("Bob",100),("Mike",50)]
|
||||
|
||||
transfer :: String -> String -> Int -> Map.Map String Int -> Map.Map String Int
|
||||
transfer from to amount bank = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 11: given an Array, find the index of the largest element. You
|
||||
-- can assume the Array isn't empty.
|
||||
--
|
||||
-- Hint: check out Data.Array.indices or Data.Array.assocs
|
||||
|
||||
maxIndex :: (Ix i, Ord a) => Array i a -> i
|
||||
maxIndex = todo
|
||||
@@ -0,0 +1,204 @@
|
||||
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
|
||||
|
||||
module Set4aTest where
|
||||
|
||||
import Control.Monad
|
||||
import Data.Array
|
||||
import Data.List
|
||||
import qualified Data.Map as Map
|
||||
import Test.QuickCheck
|
||||
|
||||
import Mooc.Th
|
||||
import Mooc.Test
|
||||
|
||||
import Set4a
|
||||
|
||||
main = score tests
|
||||
|
||||
tests = [(1,"allEqual",[ex1])
|
||||
,(2,"distinct",[ex2_int, ex2_char])
|
||||
,(3,"middle",[ex3_char, ex3_int])
|
||||
,(4,"rangeOf",[ex4_int, ex4_integer, ex4_double])
|
||||
,(5,"longest",[ex5_int, ex5_char])
|
||||
,(6,"incrementKey",[ex6_bool_float, ex6_char_int])
|
||||
,(7,"average",[ex7])
|
||||
,(8,"winner",[ex8_winner, ex8_tie])
|
||||
,(9,"freqs",[ex9_bool, ex9_int])
|
||||
,(10,"transfer",[ex10_success, ex10_missing, ex10_notEnough])
|
||||
,(11,"maxIndex",[ex11_bool, ex11_int])]
|
||||
|
||||
-- -- -- -- -- -- -- --
|
||||
|
||||
m_ex1_true example = forAll_ $ \(cnt,v) ->
|
||||
$(testing [|allEqual (replicate cnt (v `asTypeOf` example))|]) (?==True)
|
||||
m_ex1_false example = forAll_ $ \(v,NonEmpty vs) ->
|
||||
not (elem (v `asTypeOf` example) vs) ==> $(testing [|allEqual (v:vs)|]) (?==False)
|
||||
|
||||
ex1 = conjoin [m_ex1_true True
|
||||
,m_ex1_true 'a'
|
||||
,m_ex1_false 'a'
|
||||
,m_ex1_true (1::Int)
|
||||
,m_ex1_false (1::Int)]
|
||||
|
||||
m_ex2 domain = forAllBlind (sublistOf domain) $ \xs ->
|
||||
conjoin [forAllBlind (shuffle xs) $ \xs' -> $(testing [|distinct xs'|]) (?==True)
|
||||
,not (null xs) ==> forAllBlind (shuffle (head xs:xs)) $ \xs' -> $(testing [|distinct xs'|]) (?==False)]
|
||||
|
||||
ex2_int = m_ex2 [1::Int,2,3,4]
|
||||
|
||||
ex2_char = m_ex2 ['a'..'z']
|
||||
|
||||
|
||||
|
||||
m_ex3 c =
|
||||
let d = succ c
|
||||
e = succ d
|
||||
in forAllBlind (shuffle [c,d,e]) $ \[x,y,z] ->
|
||||
$(testing [|middle x y z|]) (?==d)
|
||||
|
||||
ex3_char = forAllBlind (choose ('a','y')) m_ex3
|
||||
ex3_int = forAllBlind (choose (0::Int,20)) m_ex3
|
||||
|
||||
genRangeOf delta = do
|
||||
base <- arbitrary
|
||||
vs <- listOf1 (choose (base, base+delta))
|
||||
shuffle (base:base+delta:vs)
|
||||
|
||||
m_ex4 delta = forAllBlind (genRangeOf delta) $ \vs ->
|
||||
$(testing [|rangeOf vs|]) (?==delta)
|
||||
|
||||
ex4_int = forAllBlind (choose (1::Int,10)) m_ex4
|
||||
ex4_integer = forAllBlind (choose (1::Integer,10)) m_ex4
|
||||
ex4_double = property $ do
|
||||
delta <- elements [1::Int,3,5,7,9]
|
||||
vs <- genRangeOf delta
|
||||
return $ $(testing [|rangeOf (map conv vs)|]) (?~=conv delta)
|
||||
where conv x = fromIntegral x / 2
|
||||
|
||||
ex5_int =
|
||||
forAllBlind (choose (2,10)) $ \l ->
|
||||
forAllBlind (vectorOf l (arbitrary :: Gen Int)) $ \ans ->
|
||||
forAllBlind (listOf (choose (1,l - 1) >>= vector)) $ \rest ->
|
||||
forAllBlind (shuffle (ans:rest)) $ \input ->
|
||||
$(testing [|longest input|]) (?==ans)
|
||||
|
||||
ex5_char = property $ do
|
||||
c <- choose ('a','k')
|
||||
d <- choose ('a','z') `suchThat` (>c)
|
||||
len <- choose (1,3)
|
||||
crest <- vectorOf len (choose ('a','z'))
|
||||
drest <- vectorOf len (choose ('a','z'))
|
||||
wrong <- vectorOf len (choose ('a','z'))
|
||||
input <- shuffle [c:crest, d:drest, wrong]
|
||||
return $ $(testing [|longest input|]) (?==(c:crest))
|
||||
|
||||
ex6_bool_float =
|
||||
property $ do
|
||||
c <- choose (True,False)
|
||||
let f i = fromIntegral i + 0.5
|
||||
i <- f <$> choose (0,10::Int)
|
||||
j <- f <$> choose (0,10::Int)
|
||||
let inp = [(c,i),(c,j)]
|
||||
return $ $(testing [|incrementKey c inp|]) (?==[(c,i+1),(c,j+1)])
|
||||
|
||||
ex6_char_int =
|
||||
property $ do
|
||||
is <- vectorOf 5 $ choose (0,20::Int)
|
||||
ks <- vectorOf 5 $ choose ('a','g')
|
||||
c <- choose ('a','h')
|
||||
let inp = zip ks is
|
||||
out = zipWith (\k i -> if k==c then (k,succ i) else (k,i)) ks is
|
||||
return $ $(testing [|incrementKey c inp|]) (?== out)
|
||||
|
||||
|
||||
|
||||
ex7 = conjoin [forAll_ $ \(Small i) -> $(testing [|average [fromIntegral i :: Float]|]) (?==fromIntegral i)
|
||||
,forAllBlind (choose (1,10)) $ \n -> forAll_ $ \(i::Rational) ->
|
||||
$(testing [|average (replicate n i)|]) (?==i)
|
||||
,forAll_ $ \(Small i) -> let f = fromIntegral i in $(testing [|average [f-1,f,f+1]|]) (?==f)
|
||||
,forAll_ $ \(Small i,Small j) ->
|
||||
let x = fromIntegral i :: Double
|
||||
y = fromIntegral j :: Double
|
||||
in $(testing [|average (replicate 10 x ++ replicate 10 y)|]) (?~=(x+y)/2)]
|
||||
ex8_winner = property $
|
||||
do names <- shuffle ["Mike","Bob","Lisa","Jane"]
|
||||
let (win:lose:third:_) = names
|
||||
loseScore <- choose (0,10000)
|
||||
diff <- choose (0,10000)
|
||||
thirdScore <- choose (0,20000)
|
||||
let inp = Map.fromList [(win,loseScore+diff),(lose,loseScore),(third,thirdScore)]
|
||||
return $ conjoin [$(testing [|winner inp win lose|]) (?==win)
|
||||
,$(testing [|winner inp lose win|]) (?==win)]
|
||||
|
||||
ex8_tie = property $
|
||||
do names <- shuffle ["Mike","Bob","Lisa","Jane"]
|
||||
let (first:second:third:_) = names
|
||||
score <- choose (0,10000)
|
||||
thirdScore <- choose (0,20000)
|
||||
let inp = Map.fromList [(first,score),(second,score),(third,thirdScore)]
|
||||
return $ $(testing [|winner inp first second|]) (?==first)
|
||||
|
||||
ex9_bool = forAll_ $ \bs ->
|
||||
$(testing [|freqs bs|]) . was $ \m ->
|
||||
let (t,f) = partition id bs
|
||||
ntrue = length t
|
||||
nfalse = length f
|
||||
out = Map.assocs m
|
||||
in conjoin [counterexample (" Number of True values should be "++show ntrue) $
|
||||
null t || (True,ntrue) `elem` out
|
||||
,counterexample (" Number of False values should be "++show nfalse) $
|
||||
null f || (False,nfalse) `elem` out]
|
||||
|
||||
ex9_int = forAll_ $ \(is::[Int]) ->
|
||||
$(testing [|freqs is|]) . was $ \out ->
|
||||
let vals = nub is
|
||||
in counterexample " Number of keys" (length (Map.keys out) ?== length vals)
|
||||
.&&.
|
||||
conjoin (map (ck out is) vals)
|
||||
where ck out vals i = let exp = length (filter (==i) vals)
|
||||
in counterexample (" Should contain "++show(i,exp)) $ (i,exp) `elem` (Map.assocs out)
|
||||
|
||||
ex10_success = property $
|
||||
do names <- shuffle ["Mike","Bob","Lisa","Jane"]
|
||||
let (from:to:third:_) = names
|
||||
fromBal <- choose (0,100)
|
||||
toBal <- choose (0,100)
|
||||
thirdBal <- choose (0,100)
|
||||
amount <- choose (0,100)
|
||||
let inp = Map.fromList [(from,fromBal+amount),(to,toBal),(third,thirdBal)]
|
||||
let out = Map.fromList [(from,fromBal),(to,toBal+amount),(third,thirdBal)]
|
||||
return $ $(testing [|transfer from to amount inp|]) (?==out)
|
||||
|
||||
ex10_missing = property $
|
||||
do names <- shuffle ["Mike","Bob","Lisa","Jane"]
|
||||
let (present:missing:third:_) = names
|
||||
bal <- oneof [return 0, choose (0,100)]
|
||||
thirdBal <- choose (0,100)
|
||||
amount <- choose (0,100)
|
||||
let inp = Map.fromList [(present,bal),(third,thirdBal)]
|
||||
return $ conjoin [$(testing [|transfer present missing amount inp|]) (?==inp)
|
||||
,$(testing [|transfer missing present amount inp|]) (?==inp)]
|
||||
|
||||
ex10_notEnough = property $
|
||||
do names <- shuffle ["Mike","Bob","Lisa","Jane"]
|
||||
let (from:to:third:_) = names
|
||||
fromBal <- choose (0,100)
|
||||
toBal <- choose (0,100)
|
||||
thirdBal <- choose (0,100)
|
||||
amount <- choose (1,100)
|
||||
let inp = Map.fromList [(from,fromBal),(to,toBal),(third,thirdBal)]
|
||||
return $ $(testing [|transfer from to (fromBal+amount) inp|]) (?==inp)
|
||||
|
||||
ex11_bool = property $
|
||||
do small <- choose (0,100::Int)
|
||||
diff <- choose (1,100)
|
||||
return $ conjoin [$(testing [|maxIndex (array (False,True) [(False,small),(True,small+diff)])|]) (?==True)
|
||||
,$(testing [|maxIndex (array (False,True) [(True,small),(False,small+diff)])|]) (?==False)]
|
||||
|
||||
ex11_int = property $
|
||||
do low <- choose (0,100::Int)
|
||||
hi <- choose (low+1,low+10)
|
||||
mid <- choose (low,hi)
|
||||
val <- choose (0,100::Int)
|
||||
let inp = array (low,hi) [(i,if i==mid then val+1 else val) | i <- [low..hi]]
|
||||
return $ $(testing [|maxIndex inp|]) (?==mid)
|
||||
@@ -0,0 +1,99 @@
|
||||
-- Exercise set 4b: folds
|
||||
|
||||
module Set4b where
|
||||
|
||||
import Mooc.Todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 1: countNothings with a fold. The function countNothings from
|
||||
-- the course material can be easily implemented using foldr. Your
|
||||
-- task is to define countHelper so that the following
|
||||
-- definition of countNothings works.
|
||||
--
|
||||
-- Hint: You can start by trying to add a type signature for countHelper.
|
||||
--
|
||||
-- Challenge: look up the maybe function and use it in countHelper.
|
||||
--
|
||||
-- Examples:
|
||||
-- countNothings [] ==> 0
|
||||
-- countNothings [Just 1, Nothing, Just 3, Nothing] ==> 2
|
||||
|
||||
countNothings :: [Maybe a] -> Int
|
||||
countNothings xs = foldr countHelper 0 xs
|
||||
|
||||
countHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 2: myMaximum with a fold. Just like in the previous exercise,
|
||||
-- define maxHelper so that the given definition of myMaximum works.
|
||||
--
|
||||
-- Examples:
|
||||
-- myMaximum [] ==> 0
|
||||
-- myMaximum [1,3,2] ==> 3
|
||||
|
||||
myMaximum :: [Int] -> Int
|
||||
myMaximum [] = 0
|
||||
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
|
||||
-- slHelper and slStart so that the given definition of sumAndLength
|
||||
-- works. This could be used to compute the average of a list.
|
||||
--
|
||||
-- Start by giving slStart and slHelper types.
|
||||
--
|
||||
-- Examples:
|
||||
-- sumAndLength [1.0,2.0,4.0] ==> (7.0,3)
|
||||
|
||||
|
||||
sumAndLength :: [Double] -> (Double,Int)
|
||||
sumAndLength xs = foldr slHelper slStart xs
|
||||
|
||||
slStart = todo
|
||||
slHelper = todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Ex 6: implement concat with with a fold. Define concatHelper and
|
||||
-- concatStart so that the given definition of myConcat works.
|
||||
--
|
||||
-- Examples:
|
||||
-- myConcat [[1,2,3],[4,5],[6]] ==> [1,2,3,4,5,6]
|
||||
|
||||
myConcat :: [[a]] -> [a]
|
||||
myConcat xs = foldr concatHelper concatStart xs
|
||||
|
||||
concatStart = todo
|
||||
concatHelper = todo
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
|
||||
|
||||
module Set4bTest where
|
||||
|
||||
import Data.Char
|
||||
import Data.List
|
||||
import Test.QuickCheck
|
||||
|
||||
import Mooc.Th
|
||||
import Mooc.Test
|
||||
|
||||
import Set4b
|
||||
|
||||
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])]
|
||||
|
||||
ex1_countNothings = property $ do
|
||||
justs <- fmap (map Just) $ listOf (choose (0::Int,10))
|
||||
nothings <- listOf (return Nothing)
|
||||
input <- shuffle (justs++nothings)
|
||||
return $
|
||||
counterexample ("input = "++show input) $
|
||||
$(testing' [|foldr countHelper 0 input|]) (?==length nothings)
|
||||
|
||||
ex2_myMaximum = property $ do
|
||||
x <- choose (-100::Int,100)
|
||||
xs <- listOf (choose (-100,100::Int))
|
||||
return $
|
||||
counterexample ("x = "++show x) $
|
||||
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 =
|
||||
forAllBlind (listOf niceDouble) $ \(ds::[Double]) ->
|
||||
counterexample ("ds = "++show ds) $
|
||||
$(testing' [|foldr slHelper slStart ds|]) (?==(sum ds, length ds))
|
||||
|
||||
ex6_myConcat =
|
||||
forAll_ $ \(xs :: [[Int]]) ->
|
||||
counterexample ("xs = "++show xs) $
|
||||
$(testing' [|foldr concatHelper concatStart xs|]) (?==concat xs)
|
||||
Reference in New Issue
Block a user