Skip to content

Instantly share code, notes, and snippets.

@bcomnes
Created August 14, 2014 21:06
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save bcomnes/c636d6fff9ddc5031208 to your computer and use it in GitHub Desktop.
Just just haskell Ted gave to me
------------------------------------------------------------------------
CS457/557 Functional Languages, Winter 2014 Homework 3
------------------------------------------------------------------------
> import Control.Applicative((<$>),(<*>))
> import Data.List(intersperse, transpose)
> import Test.QuickCheck(quickCheck)
> import Test.QuickCheck.Arbitrary(Arbitrary, arbitrary)
> import Test.QuickCheck.Gen(choose, vectorOf)
> data Pic = Pic { h :: Int, w :: Int, img :: [String] }
> deriving (Show, Eq)
> height :: Pic -> Int
> height (Pic h w img) = h
> width :: Pic -> Int
> width (Pic h w img) = w
------------------------------------------------------------------------
Question 1:
-----------
> valid :: Pic -> Bool
> valid (Pic h w img) = length img == h && all ((== w) . length) img
>
> propArbitraryPicValid :: Pic -> Bool
> propArbitraryPicValid pic = valid pic
>
> newtype StringLength = StringLength { getStringLength :: Int } deriving (Show, Eq)
> instance Arbitrary StringLength where
> arbitrary = choose (0, 100) >>= (\n -> return $ StringLength n)
>
> instance Arbitrary Pic where
> arbitrary = do
> h <- choose (1, 20) -- needs at least 1 column, 1 row
> w <- choose (1, 20) -- keep them small so tests run quickly
> img <- vectorOf h $ vectorOf w arbitrary
> return $ Pic h w img
>
> newtype PicList = PicList { getPicList :: [Pic] } deriving (Show, Eq)
> instance Arbitrary PicList where
> arbitrary = do
> n <- choose (1,10) -- really need to keep this small
> ps <- vectorOf n arbitrary
> return $ PicList ps
> propValid1 :: Bool
> propValid1 = not . valid $ Pic 2 6 ["hello,", "world"]
>
> propValid2 :: Bool
> propValid2 = valid $ Pic 2 6 ["hello,", "world!"]
> render :: Pic -> IO ()
> render (Pic h w img) = putStr (unlines img)
And so it runs...
> render $ Pic 2 6 ["hello,", "world!"]
hello,
world!
> letterR = Pic 5 5 ["RRRR ",
> "R R",
> "RRR ",
> "R R ",
> "R R"]
And so it runs...
> render letterR
RRRR
R R
RRR
R R
R R
> empty :: Pic
> empty = Pic 0 0 []
> string :: String -> Pic
> string s = Pic 1 (length s) [s]
------------------------------------------------------------------------
Question 2:
-----------
> block :: Int -> Int -> Char -> Pic
> block h w c = Pic h w [ cs | let cs = [c | _ <- [1..w]]
> , _ <- [1..h]]
> propBlock :: Bool
> propBlock = block 3 7 'a' == Pic 3 7 ["aaaaaaa"
> ,"aaaaaaa"
> ,"aaaaaaa"]
------------------------------------------------------------------------
> blka, blkb :: Pic
> blka = block 5 8 'A'
> blkb = block 7 4 'B'
> blank :: Int -> Int -> Pic
> blank h w = block h w ' '
> hspace :: Int -> Pic
> hspace w = blank 0 w
> vspace :: Int -> Pic
> vspace h = blank h 0
------------------------------------------------------------------------
Question 3:
-----------
> hflip :: Pic -> Pic
> hflip p@(Pic _ _ img) = p { img = reverse img }
> vflip :: Pic -> Pic
> vflip p@(Pic _ _ img) = p { img = map reverse img }
> -- flip over the upper-left to lower-right diagonal
> dflip :: Pic -> Pic
> dflip (Pic h w img) = Pic w h $ transpose img
> rot90 :: Pic -> Pic
> rot90 (Pic h w img) = Pic w h $ transpose $ reverse img
> rot180 :: Pic -> Pic
> rot180 = vflip . hflip
> propRot180 :: Pic -> Bool
> propRot180 p = rot180 p == (rot90 . rot90 $ p)
> rot270 :: Pic -> Pic
> rot270 (Pic h w img) = Pic w h $ reverse $ transpose img
> propRot270 :: Pic -> Bool
> propRot270 p = (rot90 . rot90 . rot90 $ p) == rot270 p
> -- * laws * does D8 work?
> sqi = ["ba"
> ,"cd"]
> sq = Pic 2 2 sqi
> -- test I = R^4 = F^2
> -- bundled in "rotations commute"
> propIdentities p = all ((== p) . ($ p)) [rot90 . rot90 . rot90 . rot90
> ,rot180 . rot180
> ,rot270 . rot90
> ,rot90 . rot270
> ,dflip . dflip
> ,hflip . hflip
> ,vflip . vflip]
> -- test D8: RF = F(R^3)
> propRFEqFR3 p = (dflip . rot90 $ p) == (rot90 . rot90 . rot90 . dflip $ p)
> -- test D8: (R^3)F = FR
> propR3FEqFr p = (dflip . rot90 . rot90 . rot90 $ p) == (rot90 . dflip $ p)
> -- test D8: F(R^2) = (R^2)F
> propFR2EqR2F p = (rot90 . rot90 . dflip $ p) == (dflip . rot90 . rot90 $ p)
> -- it's pretty interesting that the D8 laws hold for non-squares...
> -- Future work: I think that proving the equivalence classes are the same
> -- is as good as generating a Cayley table, but maybe that would be cool.
> cI = id
> cR = rot90
> cR2 = rot180
> cR3 = rot270
> cF = dflip
> cRF = cR . cF
> cR2F = cR2 . cF
> cR3F = cR3 . cF
> d8 = [ cI , cR , cR2 , cR3 , cF , cRF , cR2F , cR3F]
> d8Names = ["cI","cR","cR2","cR3","cF","cRF","cR2F","cR3F"]
>
> stringCompose x = (++ (" . " ++ x))
>
> cayleyTable op elems = map (\x -> map (x `op`) elems) elems
> d8CompositionNames = cayleyTable stringCompose d8Names
>
>
> cell cp = let hB = string $ "+" ++ replicate (w cp) '-'
> vB = align left $ map string $ replicate (h cp) "|"
> in align top [vB, align left [hB, cp]]
> --table cpss =
> -- these are really unit tests, but they're simple so QuickCheck is fine.
> propRHflip = hflip letterR == Pic 5 5 ["R R"
> ,"R R "
> ,"RRR "
> ,"R R"
> ,"RRRR "]
>
> propRVflip = vflip letterR == Pic 5 5 [" RRRR"
> ,"R R"
> ," RRR"
> ," R R"
> ,"R R"]
>
> propRRot90 = rot90 letterR == Pic 5 5 ["RRRRR"
> ," R R"
> ," R R"
> ," R R"
> ,"R R "]
>
> propRRot180 = rot180 letterR == Pic 5 5 ["R R"
> ," R R"
> ," RRR"
> ,"R R"
> ," RRRR"]
>
> propRRot270 = rot270 letterR == Pic 5 5 [" R R"
> ,"R R "
> ,"R R "
> ,"R R "
> ,"RRRRR"]
------------------------------------------------------------------------
Question 4:
-----------
> -- * law * (your example)
> wellBehavedPappends :: [Pic -> Pic -> Pic]
> wellBehavedPappends = [left, right, top, bottom]
>
> allWBPappends :: ((Pic -> Pic -> Pic) -> Bool) -> Bool
> allWBPappends = flip all wellBehavedPappends
>
> propPappendsAssociative :: Pic -> Pic -> Pic -> Bool
> propPappendsAssociative p q r = allWBPappends (\op -> p `op` (q `op` r)
> ==
> (p `op` q) `op` r)
> -- * caveat * center/middle aren't always associative because `div`
> -- isn't always associative, e.g. (4 `div` 3) `div` 2 /= 4 `div` (3 `div` 2)
> propAssociativityCounterexample :: Bool
> propAssociativityCounterexample = let p = Pic 1 2 ["as"]
> q = Pic 1 3 ["123"]
> r = Pic 1 4 ["wxyz"]
> left = (p `center` q) `center` r
> right = p `center` (q `center` r)
> in left /= right
> -- * law *
> propPappendsLeftIdentity :: Pic -> Bool
> propPappendsLeftIdentity p = allWBPappends (\op -> empty `op` p == p)
>
> propPappendsRightIdentity :: Pic -> Bool
> propPappendsRightIdentity p = allWBPappends (\op -> p `op` empty == p)
> -- * law *
> propPicsClosedUnderPappends :: Pic -> Pic -> Bool
> propPicsClosedUnderPappends p q = allWBPappends (\op -> valid $ p `op` q)
We have left and right identity, associativity, and closure, so for any op in
the wellBehavedPappends, <Pic, op> forms a monoid. I can't think of a way to
make inverses, so I don't believe groups can be formed in this way.
> -- * law-ish *
top, middle, bottom, left, center, and right are all instances of a
higher-order binary operation on Pics, pappend. The binary operation iop needs
the dimensions of the left and right Pics (not just their img members) in order
to be fully general. This has resulted in the ugly iop' definition below, but
I imagine that if I thought about this some more I could come up with a better
refactored solution in which the picture dimensions are naturally in scope when
iop is evaluated. The upshot is that all of our Pic binary operations are
composed of smaller binary operations.
> pappend :: (Int -> Int -> Int)
> -> (Int -> Int -> Int)
> -> (Int -> Int -> Pic -> Pic ->
> [String] -> [String] -> [String])
> -> Pic -> Pic
> -> Pic
> pappend hop wop iop pl pr = let h' = h pl `hop` h pr
> w' = w pl `wop` w pr
> iop' = iop h' w' pl pr -- refactoring fail
> img' = img pl `iop'` img pr
> in Pic h' w' img'
> miop :: (b -> a -> a)
> -> b -> b -> c -> c -> [a] -> [a]
> -> [a]
> miop pad _ w' _ _ imgl imgr = map (pad w') $ imgl ++ imgr
>
> infixr `left`, `right`, `center`
> left, right, center :: Pic -> Pic -> Pic
> left = pappend (+) max (miop rpad)
> right = pappend (+) max (miop lpad)
> center = pappend (+) max (miop cpad)
> propBlkaLeftBlkb :: Bool
> propBlkaLeftBlkb = blka `left` blkb == Pic 12 8 ["AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"BBBB "
> ,"BBBB "
> ,"BBBB "
> ,"BBBB "
> ,"BBBB "
> ,"BBBB "
> ,"BBBB "]
> propBlkaRightBlkb :: Bool
> propBlkaRightBlkb = blka `right` blkb == Pic 12 8 ["AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ," BBBB"
> ," BBBB"
> ," BBBB"
> ," BBBB"
> ," BBBB"
> ," BBBB"
> ," BBBB"]
> propBlkaCenterBlkb :: Bool
> propBlkaCenterBlkb = blka `center` blkb == Pic 12 8 ["AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ,"AAAAAAAA"
> ," BBBB "
> ," BBBB "
> ," BBBB "
> ," BBBB "
> ," BBBB "
> ," BBBB "
> ," BBBB "]
> lpad' :: a -> Int -> [a] -> [a]
> lpad' dummy n s = let d = n - length s in replicate d dummy ++ drop (- d) s
>
> lpad :: Int -> String -> String
> lpad = (lpad' ' ')
> rpad' :: a -> Int -> [a] -> [a]
> rpad' dummy n s = let d = n - length s in take n s ++ replicate d dummy
>
> rpad :: Int -> String -> String
> rpad = rpad' ' '
> cpad' :: a -> Int -> [a] -> [a]
> cpad' dummy n s = let d = n - length s
> rd = d `div` 2 -- I think this breaks associativity
> ld = d - rd
> in replicate ld dummy ++ (take n . drop (- ld) $ s) ++ replicate rd dummy
>
> cpad :: Int -> String -> String
> cpad = cpad' ' '
> propPadExample1 :: Bool
> propPadExample1 = [ pad 8 "hello" | pad <- [lpad, rpad, cpad] ] == [" hello","hello "," hello "]
> propPadExample2 :: Bool
> propPadExample2 = [ pad 3 "hello" | pad <- [lpad, rpad, cpad] ] == ["llo","hel","ell"]
> propPadLengthN :: StringLength -> String -> Bool
> propPadLengthN (StringLength n) s = all (== n) [ length $ f n s | f <- [lpad, rpad, cpad] ]
------------------------------------------------------------------------
Question 5:
-----------
> align :: (Pic -> Pic -> Pic) -> [Pic] -> Pic
> align op = foldl1 op
> -- * law *
> -- here's another way to show that pappends are associative!
> propPappendFoldsBothWays :: PicList -> Bool
> propPappendFoldsBothWays (PicList ps) = allWBPappends (\op -> foldl1 op ps == foldr1 op ps)
> aligns :: [Pic]
> aligns = map string ["this", "is", "fun!"]
> propAlignL = align left aligns == Pic 3 4 ["this"
> ,"is "
> ,"fun!"]
> propAlignC = align center aligns == Pic 3 4 ["this"
> ," is "
> ,"fun!"]
> propAlignR = align right aligns == Pic 3 4 ["this"
> ," is"
> ,"fun!"]
> text :: [String] -> Pic
> text = align left . map string
> lparen :: Int -> Pic
> lparen h = text ([" /"] ++ replicate h "|" ++ [" \\"])
> rparen :: Int -> Pic
> rparen h = text (["\\"] ++ replicate h " |" ++ ["/"])
> parens :: Pic -> Pic
> parens p = lparen h `middle` p `middle` rparen h
> where h = height p
And so it runs...
> render $ parens $ parens blkb `middle` text ["this","is","still","fun!"]
/ \
| / \ |
| | BBBB | |
| | BBBB | |
| | BBBB |this |
| | BBBB |is |
| | BBBB |still |
| | BBBB |fun! |
| | BBBB | |
| \ / |
\ /
------------------------------------------------------------------------
Question 6:
-----------
> iappend :: (Int -> Int -> [[a]] -> [[a]])
> -> Int -> Int -> Pic -> Pic
> -> [[a]] -> [[a]]
> -> [[a]]
> iappend pad h' w' pl pr imgl imgr = zipWith (++) (pad h' (w pl) imgl)
> (pad h' (w pr) imgr)
> infixr `top`, `bottom`, `middle`
> top, bottom, middle :: Pic -> Pic -> Pic
> top = pappend max (+) (iappend bpad)
> bottom = pappend max (+) (iappend tpad)
> middle = pappend max (+) (iappend mpad)
> propBlkaTopBlkb :: Bool
> propBlkaTopBlkb = blka `top` blkb == Pic 7 12 ["AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ," BBBB"
> ," BBBB"]
> propBlkaMiddleBlkb :: Bool
> propBlkaMiddleBlkb = blka `middle` blkb == Pic 7 12 [" BBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ," BBBB"]
> propBlkaBottomBlkb :: Bool
> propBlkaBottomBlkb = blka `bottom` blkb == Pic 7 12 [" BBBB"
> ," BBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"
> ,"AAAAAAAABBBB"]
> tpad :: Int -> Int -> [String] -> [String]
> tpad h w = lpad' (replicate w ' ') h
> bpad :: Int -> Int -> [String] -> [String]
> bpad h w = rpad' (replicate w ' ') h
> mpad :: Int -> Int -> [String] -> [String]
> mpad h w = cpad' (replicate w ' ') h
> propHaskellRocks :: Bool
> propHaskellRocks = tpad 3 7 ["Haskell", "rocks! "] == [" ","Haskell","rocks! "]
And so it runs...
> render $ align top $ take 5 $ cycle [blka,blkb]
AAAAAAAABBBBAAAAAAAABBBBAAAAAAAA
AAAAAAAABBBBAAAAAAAABBBBAAAAAAAA
AAAAAAAABBBBAAAAAAAABBBBAAAAAAAA
AAAAAAAABBBBAAAAAAAABBBBAAAAAAAA
AAAAAAAABBBBAAAAAAAABBBBAAAAAAAA
BBBB BBBB
BBBB BBBB
------------------------------------------------------------------------
Question 7:
-----------
> hborder :: Int -> Pic -> Pic
> hborder n p = align top [hspace n, p, hspace n]
> vborder :: Int -> Pic -> Pic
> vborder n p = align left [vspace n, p, vspace n]
> border :: Int -> Pic -> Pic
> border b = vborder b . hborder b
> -- * law *
> propBordersCommute :: StringLength -> Pic -> Bool
> propBordersCommute (StringLength n) p = border n p == redrob n p
> where redrob b = hborder b . vborder b
This function adds a horizontal border of b blank vertical lines to the left
and right of p (each height (h p)), then adds to the result of that a vertical
border of b blank horizontal lines (each of width (h p + 2 * b)). So it adds a
blank "frame" that's b thick on any side. vborder b and hborder b commute, so
defining border b = hborder b . vborder b produces the exact same result
(demonstrated by propBordersCommute).
------------------------------------------------------------------------
Question 8:
-----------
> vpad, hpad :: Int -> (Pic -> Pic -> Pic) -> Pic -> Pic
> vpad n op p = vspace n `op` p
> hpad n op p = hspace n `op` p
> -- * laws *
> propVpadVOpsEquivalent, propVpadHOpsNoOp :: StringLength -> Pic -> Bool
> propVpadVOpsEquivalent (StringLength n) p = all (\op -> vpad n op p == vpad n left p) [center, right]
> propVpadHOpsNoOp (StringLength n) p = all (\op -> vpad n op p == p) [top, middle, bottom]
>
> propHpadHOpsEquivalent, propHpadVOpsNoOp :: StringLength -> Pic -> Bool
> propHpadHOpsEquivalent (StringLength n) p = all (\op -> hpad n op p == hpad n top p) [middle, bottom]
> propHpadVOpsNoOp (StringLength n) p = all (\op -> hpad n op p == p) [left, center, right]
vpad/hpad adds n blank lines/columns on the top/left of p, as long as op is any
one of (left, center, right)/(top, middle, bottom). Otherwise they're no-ops,
which makes sense because e.g. you can't stack horizontal padding on top of a
picture, you can only append it to the left or right. One situation in which
this is handy is generating indented text that's otherwise left-justified,
since text placement is only affected by the number of lines above/columns to
the left. E.g.:
> indent2 = hpad 2 top
> render $ align left [string "* level 1", indent2 $ text ["- level 2", "- short", "- super long"], indent2 . indent2 $ text ["i. level 3", "ii. LONGLONGLONGLONG", "iii. short"]]
* level 1
- level 2
- short
- super long
i. level 3
ii. LONGLONGLONGLONG
iii. short
These are more useful than lpad and friends because e.g. (hpad 2 top) :: Pic ->
Pic, so we can think about transforming pictures rather than internal details
of the Pic representation.
------------------------------------------------------------------------
Question 9:
-----------
> fruitSurvey :: [(String, Int)]
> fruitSurvey = [("bananas", 23), ("apples", 12),
> ("pears", 17), ("plums", 9),
> ("oranges", 10), ("berries", 34),
> ("tomatoes", 2), ("mangos", 3),
> ("pineapples", 4), ("passion fruit", 1),
> ("cherries", 15), ("limes", 8),
> ("peaches", 9)]
> histogram :: [(String,Int)] -> Pic
> histogram nameToCount = let names = map fst nameToCount
> nameCol = align right $ map string names
> counts = map snd nameToCount
> numCol = align right $ map (string . show) counts
> barCol = align left $ map (flip (block 1) '*') counts
> sep = hspace 1
> in align top $ intersperse sep [nameCol, numCol, barCol]
And so it runs...
> render $ histogram fruitSurvey
bananas 23 ***********************
apples 12 ************
pears 17 *****************
plums 9 *********
oranges 10 **********
berries 34 **********************************
tomatoes 2 **
mangos 3 ***
pineapples 4 ****
passion fruit 1 *
cherries 15 ***************
limes 8 ********
peaches 9 *********
------------------------------------------------------------------------
Question 10:
------------
> data Tree = Leaf
> | Fork Tree Int Tree
> deriving Show
> insert :: Int -> Tree -> Tree
> insert n Leaf = Fork Leaf n Leaf
> insert n (Fork l m r)
> | n <= m = Fork (insert n l) m r
> | otherwise = Fork l m (insert n r)
> sampleTree = foldr insert Leaf [34, 7, 67, 23, 86, 24, 112, 17, 73]
> picTree :: Tree -> Pic
> picTree Leaf = string "-- Leaf"
> picTree (Fork l n r) = let lp = picTree l
> rp = picTree r
> hl = h lp
> branch = align center $ map string $ ["-+-"] ++ replicate hl "|" ++ [" `-"]
> hsep = hspace 1
> vsep = vspace 1
> childCol = align left [lp, vsep, rp]
> in align top [string "--", hsep, string . show $ n, hsep, branch, childCol]
that will allow us to visualize the structure of such trees more easily,
as demonstrated by the following output:
Main> render (picTree sampleTree)
-- 73 -+--- 17 -+--- 7 -+--- Leaf
| | |
| | `--- Leaf
| |
| `--- 24 -+--- 23 -+--- Leaf
| | |
| | `--- Leaf
| |
| `--- 67 -+--- 34 -+--- Leaf
| | |
| | `--- Leaf
| |
| `--- Leaf
|
`--- 112 -+--- 86 -+--- Leaf
| |
| `--- Leaf
|
`--- Leaf
Main>
If this seems a little intimidating, then start by remembering that
every Tree value must be built using either the Leaf or the Fork
constructor, suggesting that we might be able to define picTree using
pattern matching. And as a general hint, notice that we can break down
the task of drawing a tree for a node like (Fork l n r) into the task of
drawing and then combining four smaller trees, as shown in the following
diagram (which, yes, was also produced using the functions defined in
this library):
-- n - | +- | the diagram
| | | for the left
| | | child, l,
| | | goes here
| | |
| | | --------------
| | |
| `- | the diagram
| | for the
| | right child,
| | r, goes here
In this diagram, the vertical and horizontal bars are just for the
purposes of showing how the diagram can be broken in to sections and
they are not part of the final output. Note also that the size of the
picture in the middle will likely need to be varied to match the size of
the picture in the top right corner.
------------------------------------------------------------------------
Question 11:
------------
I have included lines like:
> -- * law *
above quickCheck properties that verify laws and functions for which I'd like
to informally describe law-ish properties.
------------------------------------------------------------------------
An optional, extra exercise FOR FUN ONLY, NOT FOR CREDIT:
> leafName :: String
> leafName = "Leaf"
>
> picTree' :: Tree -> Pic
> picTree' tree = let helper Leaf = let p = string leafName in (p, w p, 0, 0)
> helper (Fork l n r) =
> let (lp, wLn, _, wLCRC) = helper l
> (rp, wRn, wRCLC, _ ) = helper r
> myName = string . show $ n
> wn = w myName
> wl = w lp
> wr = w rp
> lbranch = align left $ map string $ [" _" ++ replicate wLCRC '_'
> ,"/"]
> rbranch = align right $ map string $ [replicate wRCLC '_' ++ "_ "
> , "\\"]
> hsep = hspace 1
> vsep = vspace 1
> myCol = myName
> lCol = align right [lbranch, lp]
> rCol = align left [rbranch, rp]
> p = align top $ intersperse hsep [lCol, myCol, rCol]
> in (p, wn, wl, wr)
> in let (p, _, _, _) = helper tree in p
And so it runs...
> render $ picTree' sampleTree
_____________________________________ 73 _____________
/ \
_____ 17 _____________ _____ 112 _
/ \ / \
_ 7 _ _____ 24 _____________ _ 86 _ Leaf
/ \ / \ / \
Leaf Leaf _ 23 _ _____ 67 _ Leaf Leaf
/ \ / \
Leaf Leaf _ 34 _ Leaf
/ \
Leaf Leaf
------------------------------------------------------------------------
> main :: IO ()
> main = do
> quickCheck propArbitraryPicValid
> quickCheck propValid1
> quickCheck propValid2
> quickCheck propBlock
> quickCheck propRot180
> quickCheck propRHflip
> quickCheck propRVflip
> quickCheck propRRot90
> quickCheck propRRot180
> quickCheck propRRot270
> quickCheck propIdentities
> quickCheck propRFEqFR3
> quickCheck propR3FEqFr
> quickCheck propFR2EqR2F
> quickCheck propPadExample1
> quickCheck propPadExample2
> quickCheck propPadLengthN
> quickCheck propBlkaLeftBlkb
> quickCheck propBlkaRightBlkb
> quickCheck propBlkaCenterBlkb
> quickCheck propAlignL
> quickCheck propAlignC
> quickCheck propAlignR
> quickCheck propBlkaTopBlkb
> quickCheck propBlkaMiddleBlkb
> quickCheck propBlkaBottomBlkb
> quickCheck propHaskellRocks
> quickCheck propBordersCommute
> quickCheck propVpadVOpsEquivalent
> quickCheck propHpadHOpsEquivalent
> quickCheck propPappendsAssociative
> quickCheck propAssociativityCounterexample
> quickCheck propPicsClosedUnderPappends
> quickCheck propPappendFoldsBothWays
These tests pass:
> :main
+++ OK, passed 100 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 100 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 100 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 1 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
+++ OK, passed 1 tests.
+++ OK, passed 100 tests.
+++ OK, passed 100 tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment