1
votes

So I have this exercise with the following data type

data Nat = Zero | Succ Nat deriving (Eq,Ord,Show,Read)

This can be used to represent a natural number, for example 2 = Succ (Succ Zero). I implemented a function that checks if the number is even.

even :: Nat -> Bool
even x = count x `mod` 2 == 0

count :: Nat -> Int
count Zero = 0
count (Succ x) = 1 + count x

It works fine for Zero, but whenever I try for something different, such as count Succ Zero or count Succ (Succ Zero)

*Main> even Succ Zero

<interactive>:6:1: error:
    * Couldn't match expected type `Nat -> t' with actual type `Bool'
    * The function `evenN' is applied to two arguments,
      but its type `Nat -> Bool' has only one
      In the expression: evenN Succ Zero
      In an equation for `it': it = evenN Succ Zero
    * Relevant bindings include it :: t (bound at <interactive>:6:1)

<interactive>:6:7: error:
    * Couldn't match expected type `Nat' with actual type `Nat -> Nat'
    * Probable cause: `Succ' is applied to too few arguments
      In the first argument of `evenN', namely `Succ'
      In the expression: evenN Succ Zero
      In an equation for `it': it = evenN Succ Zero
1
even (Succ Zero) - Jorge Adriano
There's no need to convert to an Int. Hint: write mutually recursive even and odd functions. - dfeuer
Well if Nat is going to be a data type that you are going to stick with for a whiile then i guess you best write an Enum instance first. - Redu

1 Answers

7
votes

The problem is not the function itself, but you call the function like:

 even Succ  Zero

or more verbose:

(even Succ) Zero

So you here call even with Succ as parameter, Succ is a function of type Nat -> Nat, not a Nat itself. In order to pass Succ Zero to even, you need to use brackets, like:

even (Succ Zero)

That being said, one does not need to first convert the Peano number to an Int in order to check if it is even or not. One can define such function inductively as:

  1. Zero is even;
  2. (Succ Zero) is not even; and
  3. (Succ (Succ x)) is even, if and only if x is even.

So we can implement this like:

even' :: Nat -> Bool
even' Zero = True
even' (Succ Zero) = False
even' (Succ (Succ x)) = even' x

or we can introducing a "helper" function odd' :: Nat -> Bool, and use mutual recursion:

even' :: Nat -> Bool
even' Zero = True
even' (Succ x) = odd' x

odd' :: Nat -> Bool
odd' Zero = False
odd' (Succ x) = even' x