Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - typeclass extension

Tags:

haskell

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!

like image 341
Daniel Deng Avatar asked Feb 26 '26 19:02

Daniel Deng


2 Answers

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.

like image 150
Willem Van Onsem Avatar answered Feb 28 '26 08:02

Willem Van Onsem


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 :)

like image 26
Daniel Deng Avatar answered Feb 28 '26 10:02

Daniel Deng