Search code examples
haskellfunctional-programming

Couldn't match expected type `t0 -> t' with actual type `Rat'


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.


Solution

  • 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)
    

    )