'Haskell create functor with type constraints

I have this Haskell code fragment:

{-# LANGUAGE InstanceSigs #-}

module LatticePoint 
where

import Data.List    

data (Eq v) => LatticePoint v = LatticePoint{prob::Double, value::v}

instance Functor LatticePoint where
    fmap :: (Eq a, Eq b) => (a -> b) -> LatticePoint a -> LatticePoint b 
    fmap f lp = LatticePoint {prob = prob lp, value = f $ value lp}

On compilation I get the following error, which I don't understand

src/LatticePoint.hs:12:14: error:
    • No instance for (Eq a)
      Possible fix:
        add (Eq a) to the context of
          the type signature for:
            fmap :: forall a b. (a -> b) -> LatticePoint a -> LatticePoint b
    • When checking that instance signature for ‘fmap’
        is more general than its signature in the class
        Instance sig: forall a b.
                      (Eq a, Eq b) =>
                      (a -> b) -> LatticePoint a -> LatticePoint b
           Class sig: forall a b.
                      (a -> b) -> LatticePoint a -> LatticePoint b
      In the instance declaration for ‘Functor LatticePoint’
   |
12 |     fmap ::  (Eq a, Eq b) => (a -> b) -> LatticePoint a -> LatticePoint b 
   | 

         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

What I'm trying to achieve is for LatticePoint to be restricted to any type v which is an instance of Eq, and to make LatticePoint an instance of Functor.



Solution 1:[1]

Converting my comments to an answer, you typically defer the constraints to the functions that use LatticePoint in a context where the value requires an Eq constraint. This lets you define fmap.

module LatticePoint 
where

import Data.List    

data LatticePoint v = LatticePoint{prob::Double, value::v}

instance Functor LatticePoint where
    fmap :: (a -> b) -> LatticePoint a -> LatticePoint b 
    fmap f lp = LatticePoint {prob = prob lp, value = f $ value lp}

foo :: Eq a => LatticePoint a -> Whatever
foo lp = ...

If you think about it, the data structure itself doesn't care whether value can be compared for equality, only functions that use the data structure.

As a concrete example, consider a definition of (==) itself:

instance Eq a => Eq (LatticePoint a) where
    (LatticePoint p1 v1) == (LatticePoint p2 v2) = p1 == p2 && v1 == v2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Silvio Mayolo