fork(1) download
  1. {-|
  2. Module: Ex1
  3. Description: Exercise 1: Getting Started with Racket and Haskell
  4. Copyright: (c) University of Toronto, 2019
  5.   CSC324 Principles of Programming Languages, Fall 2019
  6.  
  7. Before starting, please review the exercise guidelines at
  8. <https://w...content-available-to-author-only...o.edu/~david/csc324/homework.html>.
  9.  
  10. This part of the exercise is similar in spirit to the Racket part, except using
  11. the Haskell programming language instead.
  12.  
  13. We strongly recommend completing the functions in Racket (and verifying their
  14. correctness) first, so that way your work in this part can be done by translating
  15. the syntax of Racket into Haskell.
  16.  
  17. The one /new/ idea here is the use of the QuickCheck library to use a different
  18. kind of approach to testing called /property-based testing/. We illustrate a few simple property-based tests throughout this file.
  19. -}
  20. -- This lists what this module. Don't change this!
  21. module Ex1
  22. ( celsiusToFahrenheit
  23. , nCopies
  24. , numEvens
  25. , numManyEvens
  26. )
  27. where
  28.  
  29. -- Imports used for testing purposes only.
  30. import Test.QuickCheck (Property, quickCheck, (==>))
  31.  
  32. -------------------------------------------------------------------------------
  33. -- * Note about type signatures
  34. --
  35. -- Unlike Racket, Haskell is /statically-typed/. We'll go into more detail about
  36. -- what this means later in the course, but for now we've provided type signatures
  37. -- for the functions here to simplify any compiler error messages you might
  38. -- receive. (Don't change them; they're required to compile against our tests.)
  39. -------------------------------------------------------------------------------
  40.  
  41. -- | Converts a temperature from Celsius to Fahrenheit.
  42. -- __Note__: use the @round@ function to convert from floating-point types
  43. -- to @Int@.
  44. celsiusToFahrenheit :: Float -> Int
  45. celsiusToFahrenheit temp =
  46. -- TODO: replace `undefined` with a proper function body.
  47.  
  48. -- | The simplest "property-based test" is simply a unit test; note the type.
  49. prop_celsius0 :: Bool
  50. prop_celsius0 = celsiusToFahrenheit 0 == 32
  51. prop_celsius37 :: Bool
  52. prop_celsius37 = celsiusToFahrenheit 37 == 99
  53.  
  54. -------------------------------------------------------------------------------
  55. -- * Recursion with numbers
  56. --
  57. -- For the recursive functions, we recommend doing these in two ways:
  58. --
  59. -- 1. First, write them using @if@ expressions, as you would in Racket.
  60. -- 2. Then when that works, use /pattern-matching/ to simplify the definitions
  61. -- (<http://l...content-available-to-author-only...l.com/syntax-in-functions#pattern-matching>).
  62. --
  63. -- Remember: Strings are simply lists of characters. (@String === [Char]@)
  64. -- Read more about manipulating lists at
  65. -- <http://l...content-available-to-author-only...l.com/starting-out#an-intro-to-lists>.
  66.  
  67. -- | Returns a new string that contains @n@ copies of the input string.
  68. nCopies :: String -> Int -> String
  69. nCopies s n =
  70.  
  71.  
  72. -- | This is a QuickCheck property that says,
  73. -- "If n >= 0, then when you call nCopies on a string s and int n,
  74. -- the length of the resulting string is equal to
  75. -- n * the length of the original string."
  76. --
  77. -- QuickCheck verifies this property holds for a random selection of
  78. -- inputs (by default, choosing 100 different inputs).
  79. prop_nCopiesLength :: String -> Int -> Property
  80. prop_nCopiesLength s n = n >= 0 ==> length (nCopies s n) == (length s * n)
  81.  
  82. -------------------------------------------------------------------------------
  83. -- * Recursion with lists
  84. -------------------------------------------------------------------------------
  85.  
  86. -- | Returns the number of even elements in the given list.
  87. --
  88. -- We've given you a recursive template here to start from.
  89. -- But noted as above, you can later try simplifying this definition
  90. -- using pattern matching.
  91. numEvens :: [Int] -> Int
  92. numEvens numbers =
  93. -- if null numbers
  94. -- then
  95. -- ...
  96. -- else
  97. -- let firstNumber = head numbers
  98. -- pickBetterName = numEvens (tail numbers)
  99. -- in
  100. -- ...
  101.  
  102. -- | Returns the number of inner lists that contain three or more even integers.
  103. numManyEvens :: [[Int]] -> Int
  104. numManyEvens listsOfNums =
  105.  
  106.  
  107. -- | This is a property that says, "the number returned by numEvens is
  108. -- less than or equal to the length of the original list."
  109. prop_numEvensLength :: [Int] -> Bool
  110. prop_numEvensLength nums = numEvens nums <= length nums
  111.  
  112. -- | What do you think this property says?
  113. prop_numManyEvensDoubled :: [[Int]] -> Bool
  114. prop_numManyEvensDoubled listsOfNums =
  115. let doubled = listsOfNums ++ listsOfNums
  116. in numManyEvens doubled == 2 * numManyEvens listsOfNums
  117.  
  118. -------------------------------------------------------------------------------
  119. -- * Main function (for testing purposes only)
  120. -------------------------------------------------------------------------------
  121.  
  122. -- This main function is executed when you compile and run this Haskell file.
  123. -- It runs the QuickCheck tests; we'll talk about "do" notation much later in
  124. -- the course, but for now if you want to add your own tests, just define them
  125. -- above, and add a new `quickCheck` line below.
  126. main :: IO ()
  127. main = do
  128. quickCheck prop_celsius0
  129. quickCheck prop_celsius37
  130. quickCheck prop_nCopiesLength
  131. quickCheck prop_numEvensLength
  132. quickCheck prop_numManyEvensDoubled
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
[1 of 1] Compiling Ex1              ( prog.hs, prog.o )

prog.hs:30:1: error:
    Could not find module ‘Test.QuickCheck’
    Use -v to see a list of the files searched for.
   |
30 | import Test.QuickCheck (Property, quickCheck, (==>))
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdout
Standard output is empty