Thu, 20 Dec 2001 11:00:17 +0300
Toralf Wittner <firstname.lastname@example.org>
> 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),
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 = (^)
instance Num a => Pow Integer a where pow = ?
If this succeeds, there will be also no need in new type