Haskell检查自定义数据类型是否均匀

Nev*_*ind 1 haskell types

所以我使用以下数据类型进行此练习

data Nat = Zero | Succ Nat deriving (Eq,Ord,Show,Read)
Run Code Online (Sandbox Code Playgroud)

这可以用于表示自然数,例如2 = Succ(Succ Zero).我实现了一个检查数字是否均匀的函数.

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

count :: Nat -> Int
count Zero = 0
count (Succ x) = 1 + count x
Run Code Online (Sandbox Code Playgroud)

它适用于零,但每当我尝试不同的东西,如计数Succ Zero或计数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
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 7

问题在于函数本身,而是调用函数:

 even Succ  Zero
Run Code Online (Sandbox Code Playgroud)

或者更详细:

(even Succ) Zero
Run Code Online (Sandbox Code Playgroud)

所以你这里evenSuccas参数调用,Succ是一个类型的函数Nat -> Nat,而不是一个Nat本身.为了传递Succ Zero到偶数,你需要使用括号,如:

even (Succ Zero)
Run Code Online (Sandbox Code Playgroud)

话虽这么说,一个人不是需要先皮亚诺数转换为Int以检查它是否甚至与否.人们可以归纳地定义这样的功能:

  1. Zero 甚至;
  2. (Succ Zero)不是均匀; 和
  3. (Succ (Succ x))是偶数,当且仅当x是偶数.

所以我们可以这样实现:

even' :: Nat -> Bool
even' Zero = True
even' (Succ Zero) = False
even' (Succ (Succ x)) = even' x
Run Code Online (Sandbox Code Playgroud)

或者我们可以引入一个"帮助器"函数odd' :: Nat -> Bool,并使用相互递归:

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

odd' :: Nat -> Bool
odd' Zero = False
odd' (Succ x) = even' x
Run Code Online (Sandbox Code Playgroud)