Assignment 1

due Tue 10 Sep

Copy the program below into your REPL editor. There are 5 functions to write, described by comments right above them. There is also a test program which should run when you hit the play button. Its initial output will indicate many test failures and a few coincidental successes (labeled OK), but there should not be any compiler errors:

FAIL line 46 : 0.0 ~= 4.1887902047863905
FAIL line 47 : 0.0 ~= 2144.660584850632
FAIL line 48 : 5.0 ~= 118.09733552923254
FAIL line 50 : 0.0 ~= 32.0
FAIL line 51 : 0.0 ~= 212.0
FAIL line 52 : 0.0 ~= 98.6
FAIL line 54 : 0.0 ~= 100.0
 OK  line 55 : 0.0 ~= 0.0
FAIL line 56 : 0.0 ~= 37.0
FAIL line 58 : expected true
FAIL line 59 : expected true
FAIL line 60 : expected true
FAIL line 61 : expected true
 OK  line 62 : expected false
 OK  line 63 : expected false
FAIL line 65 : '?' == 'N'
FAIL line 66 : '?' == 'k'
FAIL line 68 : "?????" == "Uryyb"
FAIL line 69 : "?????????????????????????" == "To get to the other side!"

Details about how to submit will be posted later. Just copy/paste into an email, or into a document and then attach to email. We’ll try to have a more sophisticated submission mechanism for assignment 2.

import GHC.Stack
import Data.Char

{- Look up the formula for the volume of a sphere of a
given radius. Code it below. The zero is a
placeholder, so you should replace that with an
expression involving r. -}

volumeSphere r = 0

{- Convert a temperature c from the Celsius to
Fahrenheit scale. -}

celsiusToFahrenheit c = 0

{- Convert a temperature f from Fahrenheit to Celsius. -}

fahrenheitToCelsius f = 0

{- Determine whether the given string is a palindrome,
and just return a Bool. A palindrome is the same
forward or backward (reversed). For now we're only
testing this with simple words like "ABBA" and
"racecar" but we will also think about requiring
only alphabetic characters to match, and allowing
matches to be case-insensitive, so we can detect
this as a palindrome: "Was it a car or a cat I saw?" -}

palindrome str = False

{- A "rot13" encoding of text is one where each
character is rotated 13 places around the alphabet,
so "A" becomes "N", and "N" becomes "A". This
function should take a character and return a
character. Non-alphabetic characters should be
returned as-is. To apply to an entire string, we
just use 'map' (see the test program). This requires
some more advanced Haskell techniques and library
functions, that we will cover on Monday 9/9. -}

rot13 c = '?'

-- Test program -- don't change anything below

main = do
  volumeSphere 1            @?~ 4.1887902047863905
  volumeSphere (3 + 5)      @?~ 2144.660584850632
  volumeSphere 3 + 5        @?~ 118.09733552923254

  celsiusToFahrenheit   0   @?~  32
  celsiusToFahrenheit 100   @?~ 212
  celsiusToFahrenheit  37   @?~  98.6

  fahrenheitToCelsius 212   @?~ 100
  fahrenheitToCelsius  32   @?~   0
  fahrenheitToCelsius  98.6 @?~  37

  assertTrue  $ palindrome "racecar"
  assertTrue  $ palindrome "ABBA"
  assertTrue  $ palindrome ""
  assertTrue  $ palindrome "x"
  assertFalse $ palindrome "ab"
  assertFalse $ palindrome "abb"

  rot13 'A' @?= 'N'
  rot13 'x' @?= 'k'

  map rot13 "Hello" @?= "Uryyb"
  map rot13 "Gb trg gb gur bgure fvqr!" @?= "To get to the other side!"

-- Test framework -- don't change anything below

infix  1 @?~, @?=

(@?~) :: (HasCallStack, Fractional a, Ord a, Show a)
  => a -> a -> IO ()
(@?~) a1 a2 =
  putStrLn $
  testBinRel callStack "~="
  (\a b -> abs (a-b) <= 0.00001) a1 a2

(@?=) :: (HasCallStack, Eq a, Show a) => a -> a -> IO ()
(@?=) a1 a2 =
  putStrLn $
  testBinRel callStack "==" (==) a1 a2

assertTrue :: HasCallStack => Bool -> IO ()
assertTrue expr =
  putStrLn $ testReport callStack expr "expected true"

assertFalse :: HasCallStack => Bool -> IO ()
assertFalse expr =
  putStrLn $ testReport callStack (not expr) "expected false"

testBinRel stack repr predicate a1 a2 =
  testReport stack (predicate a1 a2)
  (unwords [show a1, repr, show a2])

testReport stack pass descr =
  unwords
  [ if pass then " OK " else "FAIL"
  , "line"
  , getLineNum stack
  , ":"
  , descr
  ]

getLineNum stack =
  case getCallStack stack of
    [] -> "?"
    (_, loc):_ -> show (srcLocStartLine loc)