Reputation: 25
I have a datatype:
data AbstractInteger = Zero
| Succ AbstractInteger
| Pred AbstractInteger
deriving (Show, Eq)
I already have two functions:
1) Convert AbstractInteger into Integer:
aiToInteger :: AbstractInteger -> Integer
aiToInteger (Zero) = 0
aiToInteger (Succ next) = 1 + (aiToInteger next)
aiToInteger (Pred prev) = (aiToInteger prev) - 1
2) Addition AbstractInteger :
plusAbs :: AbstractInteger -> AbstractInteger -> AbstractInteger
plusAbs a b | aiToInteger a == 0 = b
| aiToInteger b == 0 = a
| aiToInteger a > 0 = (Succ (plusAbs (Pred a) b))
| otherwise = (Pred (plusAbs (Succ a) b))
But I don't understand how to create multiply function.
I wrote this but it's not work.
multiplyAbs :: AbstractInteger -> AbstractInteger -> AbstractInteger
multiplyAbs _ (Zero) = (Zero)
multiplyAbs (Zero) _ = (Zero)
multiplyAbs a (Succ Zero) = a
multiplyAbs (Succ Zero) b = b
multiplyAbs a b = (plusAbs a (timesAbs a (Pred(b))))
Upvotes: 0
Views: 164
Reputation: 15045
As you've implemented aiToInteger
, you might want to implement iToAi
, something like:
iToAi :: Integer -> AbstractInteger
iToAi a | a == 0 = Zero
| a < 0 = Pred (iToAi (a + 1))
| a > 0 = Succ (iToAi (a - 1))
Then plusAbs
and multiplyAbs
will come down to converting abstract integers to integers, perform the operations on them and convert them back:
plusAbs' :: AbstractInteger -> AbstractInteger -> AbstractInteger
plusAbs' a b = iToAi (aiToInteger a + aiToInteger b)
multiplyAbs' :: AbstractInteger -> AbstractInteger -> AbstractInteger
multiplyAbs' a b = iToAi (aiToInteger a * aiToInteger b)
But I'd suggest trying to implement the functions by using pattern-match on the arguments, something like:
negative :: AbstractInteger -> AbstractInteger
negative Zero = Zero
negative (Succ a) = Pred (negative a)
negative (Pred a) = Succ (negative a)
multiplyAbs :: AbstractInteger -> AbstractInteger -> AbstractInteger
multiplyAbs Zero a = Zero
multiplyAbs (Succ a) b = plusAbs (multiplyAbs a b) b
multiplyAbs (Pred a) b = plusAbs (multiplyAbs a b) (negative b)
The key point is that Succ a
can be associated with (a + 1)
, that's why (Succ a) * b
can be associated with a * b + b
. According to this logic (Pred a) * b
is converted to a * b - b
, that's why you need negative
function here.
plusAbs
is implemented similarly:
(a + 1) + b
is the same as 1 + (a + b)
(a - 1) + b
is the same as (a + b) - 1
The logic is just like in your example, but you can avoid using aiToInteger
by using pattern-match.
Upvotes: 1