I've got a question about type classes. I've got the following code:
import Foreign.C.Types (CDouble, CFloat)
class Floating a => Trigonometry a where
versin :: a -> a
versin x = 1 - cos x
vercos :: a -> a
vercos x = 1 cos x
coversin :: a -> a
coversin x = 1 - sin x
covercos :: a -> a
covercos x = 1 sin x
haversin :: a -> a
haversin x = versin x * 0.5
havercos :: a -> a
havercos x = vercos x * 0.5
hacoversin :: a -> a
hacoversin x = coversin x * 0.5
hacovercos :: a -> a
hacovercos x = covercos x * 0.5
instance Trigonometry CDouble
instance Trigonometry CFloat
instance Trigonometry Double
instance Trigonometry Float
Now my question is: there can be infinite amount of Floating instances, and obviously every single instance of Floating can be an instance of Trigonometry without extra implementation. Is there a way to avoid the explicit instance declarations at the bottom and automatically make all Floating instances become Trigonometry instance too?
Cheers!
CodePudding user response:
For those who are looking for something similar, I figured it out:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Algorithms.Math.Trigonometry where
class Floating a => Trigonometry a where
versin :: a -> a
versin x = 1 - cos x
vercos :: a -> a
vercos x = 1 cos x
coversin :: a -> a
coversin x = 1 - sin x
covercos :: a -> a
covercos x = 1 sin x
haversin :: a -> a
haversin x = versin x * 0.5
havercos :: a -> a
havercos x = vercos x * 0.5
hacoversin :: a -> a
hacoversin x = coversin x * 0.5
hacovercos :: a -> a
hacovercos x = covercos x * 0.5
instance Floating a => Trigonometry a
Language extension magic :)
CodePudding user response:
For this case, there is probably no need to define a typeclass at all, you can implement these functions as top level functions with a Floating type constraint:
versin :: Floating a => a -> a
versin x = 1 - cos x
vercos :: Floating a => a -> a
vercos x = 1 cos x
coversin :: Floating a => a -> a
coversin x = 1 - sin x
covercos :: Floating a => a -> a
covercos x = 1 sin x
haversin :: Floating a => a -> a
haversin x = versin x * 0.5
havercos :: Floating a => a -> a
havercos x = vercos x * 0.5
hacoversin :: Floating a => a -> a
hacoversin x = coversin x * 0.5
hacovercos :: Floating a => a -> a
hacovercos x = covercos x * 0.5
If you want to make a special implementation for a certain Floating type, you can indeed work with a typeclass, but if you implement an instance Floating a => Trigonometry a, you likely will end up with overlapping instances.
