-3

Integers次のように機能するように、繰り返しタイプの表現を定義します。

data Integers = Zero | Next Integers | Prev Integers

そして、この表現、クラスNumのインスタンスを作成します。これは、で使用できることを意味します(+), (*), (==), abs, signum, showIntegers

今まで私はこのようにsthを定義しました:

data Integers = Zero | Integers Int deriving (Show)

next :: Integers -> Integers
next Zero = Integers 1
next (Integers a) = Integers a + Integers 1

prev :: Integers -> Integers
prev (Integers 1) = Zero
prev (Integers a) = Integers a - Integers 1

instance Eq Integers where  
    Zero == Zero = True
    Integers a == Integers b = a == b  
    _ == _ = False

instance Num Integers where
    Integers a + Integers b = Integers (a + b)
    Integers a - Integers b = Integers (a - b)
    Integers a * Integers b = Integers (a * b)
    abs (Integers a) = Integers (abs a)
    signum (Integers a) = Integers (signum a)
    fromInteger a = Integers (fromInteger a)

data Integers = Zero | Next Integers | Prev Integersしかし、それは期待に合いません

4

1 に答える 1

9
data Integers = Zero | Next Integers | Prev Integers

お見せします+が、残りは簡単なはずです。

Zero + y = y
x + Zero = x

まあ、それは簡単でした!

おー。他にもいくつかのケースがあります。

それでも、すべてのZeroケースを処理したので、今はとだけを処理する必要がPrevありNextます。それらは互いに反対ですよね?したがって、それぞれが1つ与えられると、それらは互いにキャンセルされます。

Next x + Prev y = x + y
Prev x + Next y = x + y

今、私たちが与えられた数字が両方とも同じ符号を持っている場合についてのみ心配する必要があります。

Next x + Next y = Next (Next (x + y))
Prev x + Prev y = Prev (Prev (x + y))

(これらの最後の2つの方程式は、最も効率的な実装ではありませんが、理解するのは簡単です。)

そして、の定義は完了です+

他の関数のいくつかはより簡単で、いくつかはより困難です(そしてより簡単な関数のいくつかを再利用する必要があります)が、それらはすべて/いずれか/両方のパラメーターのパターンマッチングと適切なことを行います。そして、ほとんどの場合、それらは再帰を伴います。再帰的なデータ構造が与えられた場合、通常、あるレベルでは避けられません。

于 2012-12-13T12:07:51.740 に答える