Population

Haskell Assignment

    A.First Edition

    This is second assignment of Haskell Assignment.

    B.The problem

C.The idea of program

    D.The major functions

    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>