Haskell Assignment
A.First Edition
This is second assignment of Haskell Assignment.
C.Further improvement
It is a shameful thing to post it, however I have to do it, just record what I have done.
กก
Name: Qingzhe Huang ID: 5037735 Title: Comp348 Assignment 2 > module A2 where ------------------------------------------------------------------------------------------------- Question 1 I made two utility function to get min and max from a list of numbers minlist :: Ord a => [a] -> a > minlist (x:xs) = if xs == [] then x else if x <= minlist xs then x else minlist xs maxlist :: Ord a => [a] -> a > maxlist (x:xs) = if xs == [] then x else if x >= maxlist xs then x else maxlist xs I have to define power as a normal function since there is no member functions like it in class Floating power :: (Num a, Ord a) => Interval -> a -> Interval > power (x:<x') n = if n==0 then (1:<1) > else > if n>0 then (x:<x') * (power (x:<x') (n-1)) > else recip (power (x:<x') (-n)) definitions: (:<) :: Double -> Double -> Interval -- data constructor > data Interval = Double :< Double Show: > instance Show Interval where > show (x :< y) = "<" ++ show x ++ "," ++ show y ++ ">" Eq class: > instance Eq Interval where > (x:<x')==(y:<y') = (x==y)&&(x'==y') Ord class: I made this in order to simplify comparison of cases of "Containing Zero": if (x:<x')>=(0:<0) > instance Ord Interval where > (x:<x')>= (y:<y') = (x>=y&&x'>=y') > (x:<x')<= (y:<y') = (x<=y&&x'<=y') Num class: > instance Num Interval where > (x:<x') + (y:<y') = (x+y):<(x'+y') > (x:<x') * (y:<y') = (minlist [x*y, x*y', x'*y, x'*y']):<(maxlist [x*y, x*y', x'*y, x'*y']) > negate (x:<x') = (-x'):<(-x) Fraction class: > instance Fractional Interval where > recip (x:<x') = if (x<=0&&x'>=0) then error "containing zero" > else (1/x'):<(1/x) Floating class: since I implemented Ord class, I can use Interval comparison here. > instance Floating Interval where > sqrt (x:<x') = if ((x:<x')>=(0:<0)) then (sqrt x):<(sqrt x') > else error "non-negative error" > zero = 0:<0 > containzero = (-2.4):<5.1 > negative = (-3.2):<(-4.5) > positive = 9.0:<10.5 I like to have some message displaying on my screen > test1 = "The followings are all test for question 1" > test1a = "show dividing by zero interval" ++ show (positive/zero) > test1b = "show dividing by interval containing zero" ++ show (positive/containzero) > test1c = "show taking the square root of a non-positive interval"++ show (sqrt containzero) > test1d = "show taking the square root of zero interval "++ show (sqrt zero) > test1e = "show taking the square root of a negative interval"++ show (sqrt negative) > test1f = "show rasing an interval containing zero to a negative power "++show (power negative (-3)) ------------------------------------------------------------------------------------------------- Question 2 commutative :: Eq a => (b -> b -> a) -> b -> b -> c -> [Char] > commutative op x y _ = if op x y == op y x then "" else " commutative law fails " associative :: Eq a => (a -> a -> a) -> a -> a -> a -> [Char] > associative op x y z = if op (op x y) z == op x (op y z) then "" else " associative law fails " check :: Num a => a -> a -> a -> [Char] > check x y z = > commutative (+) x y z ++ > commutative (*) x y z ++ > associative (+) x y z ++ > associative (*) x y z > int1 = 2:<2 > int2 = 5:<5 > int3 = (-9):<(-9) > float1 = 3.5:<4.3 > float2 = 2.1:<3.9 > float3 = (-10.0):<9.9 I like to have some message displaying on my screen > test2 = "The followings are all test for question 2" > test2a = check int1 int2 int3 > test2b = check float1 float2 float3 > test2c = check int1 float2 float3 > test2d = check int3 float3 float2 ------------------------------------------------------------------------------------------------- Question 3 the accuracy is chosen for 1% > e = 0.01 I made a utility function to generate a interval with input number "d" and a setup tolarence "e" inter :: Double -> Interval > inter d = (d*(1-e)) :< (d*(1+e)) this utility function checks the "a == 0" error and negative sqrt error checkroot :: Double -> Double -> Double -> Bool > checkroot a b c = if a==0 then error " a == 0 " > else if power (inter b) 2 - (4:<4)*(inter a)*(inter c) < (0:<0) > then error " sqrt for negatives " else True solve calculates the "root" with interval solve :: Double -> Double -> Double -> (Interval,Interval) > solve a b c = if checkroot a b c then > ((-(inter b)+sqrt ((inter b)*(inter b) - (4:<4)*(inter a)*(inter c)))/((2:<2)*(inter a)), > (-(inter b)-sqrt ((inter b)*(inter b) - (4:<4)*(inter a)*(inter c)))/((2:<2)*(inter a))) > else error "error" This root function calculates the real root root :: Floating a => a -> a -> a -> (a,a) > root a b c = ((-b+sqrt(b*b -4*a*c))/(2*a),(-b-sqrt(b*b -4*a*c))/(2*a)) test data is declared here: > num1 = [1.02, 2.9, 1.4] > num2 = [4.2, 100.3,(-3.9)] > num3 = [1.001, 2.0003, 1.0001] this function simply call both solve and root function with parameter of a list of numbers assign :: [Double] -> [Char] > assign (a:(b:([c]))) = show (solve a b c) ++ "compared with roots "++ show (root a b c) I like to have some message displaying on my screen > test3 = "The followings are all test for question 3" --num1 is common > test3a = assign num1 a) with b much greater than 1, the solution has less accuracy. > test3b = assign num2 b) with roughly a= b/2 = c, there is no solution for interval > test3c = assign num3 ------------------------------------------------------------------------------------------------- Question 4 a) eqrev :: Eq a => [a] -> Bool > eqrev s = s == reverse s b)lower :: [Char] -> [Char] > lower s = map toLower s c) letters :: [Char] -> [Char] > letters s = filter isAlpha s palindrome :: [Char] -> Bool > palindrome = eqrev.lower.letters > string1 = "Evil rats on no star live" > string2 = "Able was I ere I saw Elba" > string3 = "A man! A plan! A canal! Panama!" > string4 = "This string is not palindromic." I like to have some message displaying on my screen > test4 = "The followings are all test for question 4" test4a :: [Bool] > test4a = map palindrome [string1,string2, string3, string4] -------------------------------------------------------------------------------------------------------------------------- Result of test: A2> test1 "The followings are all test for question 1" A2> test1a "show dividing by zero interval Program error: containing zero A2> test1b "show dividing by interval containing zero Program error: containing zero A2> test1c "show taking the square root of a non-positive interval Program error: non-negative error A2> test1d "show taking the square root of zero interval <0.0,0.0>" A2> test1e "show taking the square root of a negative interval Program error: non-negative error A2> test1f "show rasing an interval containing zero to a negative power <-0.0305176,-0.01 09739>" A2> A2> test2 "The followings are all test for question 2" A2> test2a "" A2> test2b " associative law fails associative law fails " A2> test2c "" A2> test2d " associative law fails " A2> test3 "The followings are all test for question 3" A2> test3a "(<-0.680682,-0.555488>,<-2.30515,-2.14778>)compared with roots (-0.616393,-2.22 674)" A2> test3b "(<-0.202401,0.280826>,<-24.403,-23.4461>)compared with roots (0.03882,-23.9198) " A2> test3c "( Program error: non-negative error A2> test4 "The followings are all test for question 4" A2> test4a [True,True,True,False] A2>