Context in Data Instances

I have a data type that only makes sense if its arguments can be ordered, however I seem to need to delve into some complex and potentially dangerous things to get it working (GADT, basically). Is what I'm doing (limited data types) considered haskell bad practice, and is there any way to do this?

For those who wish, here is the corresponding code:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
import Data.List (sort)

data OrdTriple a where
    OrdTriple :: (Ord a) => a -> a -> a -> OrdTriple a

instance Functor OrdTriple where
    fmap :: (Ord a, Ord b) => (a -> b) -> OrdTriple a -> OrdTriple b
    fmap f (OrdTriple n d x) = OrdTriple n' d' x'
        where 
            [n', d', x'] = sort [f n, f d, f x]

At first it seemed to me that I just put the context in the Functor instance (this is the only instance I am struggling with), but it seems that I cannot (not mention the hidden type), and even if I could I still need a restriction on fmap, so that its return type is ordered.

, , , -, , Functor:

No instance for (Ord a)
Possible fix:
  add (Ord a) to the context of
    the type signature for
      fmap :: (a -> b) -> OrdTriple a -> OrdTriple b
When checking that:
    forall a b.
    (Ord a, Ord b) =>
    (a -> b) -> OrdTriple a -> OrdTriple b
  is more polymorphic than:
    forall a b. (a -> b) -> OrdTriple a -> OrdTriple b
When checking that instance signature for ‘fmap’
  is more general than its signature in the class
  Instance sig: forall a b.
                (Ord a, Ord b) =>
                (a -> b) -> OrdTriple a -> OrdTriple b
     Class sig: forall a b. (a -> b) -> OrdTriple a -> OrdTriple b
In the instance declaration for ‘Functor OrdTriple’
0
1

, Functor, fmap .

. - " ", a b. (, , )

class FgFunctor f a b where
   fgmap :: (a->b) -> f a -> f b

-- regular functors are also fine-grained ones, e.g.
instance FgFunctor [] a b where
   fgmap = fmap

instance (Ord a, Ord b) => FgFunctor OrdTriple a b where
   fgmap f (OrdTriple n d x) = OrdTriple n' d' x'
      where [n', d', x'] = sort [f n, f d, f x]

Functor :

{-# LANGUAGE GADTs, KindSignatures, MultiParamTypeClasses, 
    ConstraintKinds, TypeFamilies, FlexibleInstances #-}
{-# OPTIONS -Wall #-}
module CFunctor where

import Data.List (sort)
import Data.Kind (Constraint)

data OrdTriple a where
    OrdTriple :: (Ord a) => a -> a -> a -> OrdTriple a

class CFunctor (f :: * -> *) where
   type C f a :: Constraint
   cmap :: (C f a, C f b) => (a -> b) -> f a -> f b

-- regular functors are also constrained ones, e.g.
instance CFunctor [] where
   type C [] a = a ~ a
   cmap = fmap

instance CFunctor OrdTriple where
   type C OrdTriple a = Ord a
   cmap f (OrdTriple n d x) = OrdTriple n' d' x'
      where [n', d', x'] = sort [f n, f d, f x]
+1

Source: https://habr.com/ru/post/1672701/


All Articles