0

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


  • Okay, so... compute the gcd and do the division seems like the obvious next step. Have you tried that? If no, then do; if yes, then what did you try exactly and what went wrong? – Daniel Wagner Nov 14 '20 at 06:56
  • Yes, I tried using the gcd by first getting the numbers into integers and evaluated it and then divided the numbers but how do I then convert those integers back to the form of this datatype, as I supply the input in a hardcoded manner... – Singularity Nov 14 '20 at 09:57
  • If the intention of the exercise is to reimplement numbers, then I encourage you to try to implement the gcd and division operations without resorting to conversion back into native number types. On the other hand, presumably you get to decide what is and isn't allowed in this exercise, so if you decide not to take my advice, then, well... have you tried writing a conversion from builtin numbers to your numbers? If no, then do; if yes, then what did you try exactly and what went wrong? – Daniel Wagner Nov 14 '20 at 11:41
  • (As an aside, I see you implemented `plusSign` using conversions into builtin numbers and comparisons on those; I similarly encourage you to try implementing those comparisons natively, without converting into builtin numbers first.) – Daniel Wagner Nov 14 '20 at 11:44
  • The fact that `Sign` has two ways of representing 0 (`Pos Zero` and `Neg Zero`) is a bit of a wart. – chepner Nov 14 '20 at 19:54

0 Answers0