I'm doing homework and one of the tasks is to make a function that normalises a rational number. Rational numbers here are defined by two integers ( which is already determined by the professor so I can't change that). This is what I came up with:
data Rat = Rat Integer Integer
normaliseRat :: Rat -> Rat
normaliseRat (Rat a b) = Rat (a `div` gcd a b) (b `div` gcd a b)
When I try to run the function I get this error:
<interactive>:2:1: error:
* Couldn't match expected type `t0 -> t' with actual type `Rat'
* The function `normaliseRat' is applied to two value arguments,
but its type `Rat -> Rat' has only one
In the expression: normaliseRat 6 9
In an equation for `it': it = normaliseRat 6 9
* Relevant bindings include it :: t (bound at <interactive>:2:1)
I'm completely new to Haskell and functional programming so forgive me if it's a simple solution.
CodePudding user response:
normaliseRat
expects a single Rat
argument, not the two integers you would use to build a Rat
value. Assuming your Rat
type has an appropriate Show
instance,
> normaliseRat (Rat 6 9)
Rat 2 3
If you wanted a smart constructor for Rat
that did take two Integer
arguments, that would be something like
mkRat :: Integer -> Integer -> Rat
mkRat n d = let gcd' = gcd n d
n' = n `div` gcd'
d' = d `div` gcd'
in Rat n' d'
> mkRat 6 9
Rat 2 3
(The purpose of a smart constructor is to prevent you from creating a value like Rat 6 9
in the first place, as long as you always use mkRat
in place of using Rat
directly. mkRat
can also be defined in terms of your existing normaliseRat
:
mkRat :: Integer -> Integer -> Rat
mkRat n d = normaliseRat (Rat n d)
)