Haskell检查自定义数据类型是否为偶数

时间:2018-12-04 19:23:33

标签: haskell types

所以我在练习中使用以下数据类型

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

这可以用来表示自然数,例如2 = Succ(Succ零)。 我实现了一个检查数字是否为偶数的功能。

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

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

它对零有效,但是每当我尝试不同的操作时,例如将Succ计数为零或将Succ(计数为零)计数

*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 个答案:

答案 0 :(得分:7)

问题是不是函数本身,但是您可以像这样调用函数:

 even Succ  Zero

或更详细:

(even Succ) Zero

因此,您在此处以even作为参数调用SuccSucc是类型Nat -> Nat的函数,而不是Nat本身。为了将Succ Zero传递给偶数,您需要使用方括号,例如:

even (Succ Zero)

话虽这么说,不是不需要先将Peano数转换为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

或者我们可以引入一个“ helper”函数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