Here, I have implemented a Nat(positive integers) data type and Sign(for all integers) datatype in Haskell and I have implemented their Plus functions respectively, which are working correctly. Now, I was thinking of extending these to rationals hence have introduced Ratio datatype to cover those and have implemented it's plus function respectively, but the return that I would get from these would be values in fractions that might be not in their respective simplest forms, hence I want to return from these functions only, fractions that would be simple, that is the gcd of numerator and denominator is 1. My implemented code is as follows->
data Nat = Zero | Succ Nat -- the user defined data type for Nat for non negative integers
data Sign = Neg Nat | Pos Nat -- another user defined data type which checks for the sign of the particular number and helps in converting numbers to integers with use of Sign
data Ratio = Ratio Sign Sign -- the new ratio defined datatype to use for defining the rationals
plus :: Nat -> Nat -> Nat -- the original plus function which adds two Nat datatypes
plus m Zero = m -- when one is zero, hence returning other
plus Zero m = m
plus m (Succ (n)) = Succ (plus m n) -- respectively adding using successor property
plusSign :: Sign -> Sign -> Sign -- defining the plus function which would add the two numbers
plusSign (Pos m) (Pos Zero) = Pos (plus m Zero) -- if one number is zero then give the other number only and cheking for all the respective sign cases
plusSign (Neg m) (Pos Zero) = Neg (plus m Zero)
plusSign (Pos m) (Neg Zero) = Pos (plus m Zero)
plusSign (Neg m) (Neg Zero) = Neg (plus m Zero)
plusSign (Pos m) (Pos n) = Pos (plus m n) -- if both are positive then add them respectively and give that number Pos only
plusSign (Neg m) (Neg n) = Neg (plus m n) -- if both are negative then add them, and give the part neg respectively
plusSign (Neg m) (Pos n) -- if any one particular is postive and other is negative, then adding on the basis of the conditoins given
| mvalue == nvalue = Pos Zero -- if both are equal in magnitude, then retrun Zero
| mvalue > nvalue = Neg (sub m n) -- if negative is larger, then subracting them and giving the respective sign
| mvalue < nvalue = Pos (sub m n) -- if postive is larger, then subracting them and giving the respective sign
where
mvalue = convtointSign (Neg m) -- checking on the basis of integer value
nvalue = convtointSign (Pos n)
plusSign (Pos m) (Neg n) -- hence respectively checking the other case ono the basis of opposite arguments
| mvalue == nvalue = Pos Zero -- similar defination
| mvalue < nvalue = Neg (sub m n)
| mvalue > nvalue = Pos (sub m n)
where
mvalue = convtointSign (Pos m) -- checking the magnitudes
nvalue = convtointSign (Neg n)
plusRatio :: Ratio -> Ratio -> Ratio -- defining the required rational adding funtion which would add the rationals as per required conditions
plusRatio (Ratio (Pos Zero) m) p = p -- if one of the number's numerators is zero, then give the second number back
plusRatio p (Ratio (Pos Zero) m) = p
plusRatio (Ratio (Neg Zero) m) p = p
plusRatio p (Ratio (Neg Zero) m) = p
plusRatio (Ratio m (Pos Zero)) p = error "One of the rationals defined has Denominator as Zero." -- if for one of the numbers the denominator is Zero, hence returnign error
plusRatio p (Ratio m (Pos Zero)) = error "One of the rationals defined has Denominator as Zero."
plusRatio (Ratio m (Neg Zero)) p = error "One of the rationals defined has Denominator as Zero."
plusRatio p (Ratio m (Neg Zero)) = error "One of the rationals defined has Denominator as Zero."
plusRatio (Ratio m n) (Ratio x y) = (Ratio (plusSign (multSign m y) (multSign n x)) (multSign n y)) -- else using the defined multSign function depending on the provided arguments