Home > OS >  How do I make a container for a double a Semigroup?
How do I make a container for a double a Semigroup?

Time:11-11

I am learning Haskell. Imagine I have the following:

data Coordinate = Coordinate double

I wish to implement a semigroup instance for Coordinate.

instance Semigroup (Coordinate a) where
  Coordinate a <> Coordinate b   =  Coordinate (a b)

The typechecker is displeased at me:

Expected kind ‘* -> *’, but ‘Coordinate’ has kind ‘*’
    • In the first argument ofSemigroup’, namely ‘(Coordinate a)’
      In the instance declaration for ‘Semigroup (Coordinate a)’
    |
175 | instance (Num a) => Semigroup (Coordinate a) where

(I know that this is just an empty container for a double and I could already be using just the double itself, but I am learning Haskell and I would like to understand how this works.)

CodePudding user response:

The way you specified Coordinate, it doesn't have any type parameters. So the semigroup instance head should be simply

instance Semigroup Coordinate where
  ...

Alternatively, you can give it a parameter to allow including different number types:

newtype Coordinate' a = Coordinate' { getCoordinate' :: a }

In this case, the Semigroup instance will need to mention the parameter, however just calling it a won't be enough because you can't perform on arbitrary types. You need to either restrict it to Double there

instance Semigroup (Coordinate' Double)

or to an arbitrary numerical type

instance Num a => Semigroup (Coordinate' a)

Note that in either case, Semigroup may not be the best class for the purpose, consider using AdditiveGroup and then you can also make it a VectorSpace.

  • Related