-- 自然数の構成
data Nat = Zero | Succ Nat deriving (Eq, Ord, Show)
-- 足し算と掛け算
add :: Nat -> Nat -> Nat
m `add` Zero = m
m `add` (Succ x) = Succ (m `add` x)
prod :: Nat -> Nat -> Nat
m `prod` Zero = Zero
m `prod` (Succ x) = (m `prod` x) `add` m
-- 自然数の中で引き算した気になる
-- x - y で、yが大きいときは 0にしてしまう
natSubtract :: Nat -> Nat -> Nat
natSubtract x y
| x > y = f x y Zero
| otherwise = Zero
where f x y m = if x == y then m else f x (Succ y) (Succ m)
-- 整数のこと (Zahl なので。)
-- type は 型に別名をつける。(新しい型を定義しているわけではない)
type Zah = (Nat, Nat)
normarilze :: Zah -> Zah
normarilze (x, y)
| x == Zero || y == Zero = (x, y)
| x == y = (Zero, Zero)
| x > y = (natSubtract x y, Zero)
| x < y = (Zero, natSubtract y x)
-- マイナス倍
negateZah :: Zah -> Zah
negateZah (x, y) = (y, x)
-- 絶対値
abs :: Zah -> Nat
abs (x, y) = if z == Zero then w else z
where (z, w) = normarilze (x, y)
-- 足し算と掛け算
addZah :: Zah -> Zah -> Zah
addZah (x, y) (z, w) = normarilze (x `add` z, y `add` w)
prodZah :: Zah -> Zah -> Zah
prodZah (x, y) (z, w) = normarilze ((x `prod` z) `add` (y `prod` w)
, (y `prod` z) `add` (x `prod` w))
-- 引き算
subtractZah :: Zah -> Zah -> Zah
subtractZah x y = addZah x (negateZah y)