S.D.Mechveliani mechvel@math.botik.ru
Thu, 20 Dec 2001 11:00:17 +0300

```Toralf Wittner <wittner@uni-duesseldorf.de>

writes

> [..]
> data PowerNum = INT Integer | DBL Double deriving (Eq, Show, Read)
> [..]
> Now it basically works. However wouldn't it have been easier to write
> something like this:
>
> powPos :: Integer -> Integer -> Integer
> [..]
> powNeg :: Integer -> Integer -> Double
> [..]
>	| y <  0	= 1 / fromInteger x * powNeg x (y + 1)
>
> Initially I wanted something as terse as the Python version, now I either
> have to write two functions or I need to define a type. Is there not an
> easier way to come as close as possible to the Python version?
>
> Thanks anyway - learnt a lot!

For this particular task, the most natural solution is, probably,

pow :: Fractional a => a -> Integer -> a
pow a n =
if n > 0 then a^n  else (1/a)^(- n)

(^) is of standard, only  pow  adds the facility of negative n.

Then, you need each time to convert the argument to appropriate
type of Fractional:

pow (fromInteger 2 :: Ratio.Rational) 2     --> 4 % 1
pow (fromInteger 2 :: Ratio.Rational) (-2)  --> 1 % 4
pow (2 :: Double) (-2)                      --> 0.25
pow (2 :: Integer) (-2) -->
... No instance for (Fractional Integer)

If you replace standard (and not lucky)  Fractional  with some
class  Foo  (with multiplication  mul  and  division  div),
make  Integer  an instance of  Foo
(where  div  may fail for some data),
and program
pow :: Foo a => a -> Integer -> a
via  mul, div,
then it would work like this:

pow (2 :: Integer)  2    --> 4
pow (2 :: Integer)  (-2) --> "Error: cannot invert 2 :: Integer"
pow (2 :: Rational) (-2) --> 1%4

Another way is to try to straggle with overlapping instances by
defining something like this:

class Pow a b where pow :: a -> Integer -> b

instance Num a => Pow a a       where  pow = (^)
Fractional ?
instance Num a => Pow Integer a where  pow = ?

If this succeeds, there will be also no need in new type
constructors.

-----------------
Serge Mechveliani
mechvel@botik.ru

```