Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Howto further constrain an existing type class in Haskell

Is there a way to further constrain the context of an existing type class?

For example, the type class Functor:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

This class definition does not enforce a or b to be an element of Show. Also this type class is a class that is included by myself, so i can't influence the classes definition. Is it still possible, to later allow only that a's and that b's, that are member of Show?

like image 577
frosch03 Avatar asked Mar 07 '12 09:03

frosch03


2 Answers

Not directly. The class's definition cannot be changed without changing the source and recompiling. In the case of classes defined in the standard libraries, that would cause much breaking of code, so is not a realistic option.

You can however, wrap the class and add your desired constraints,

class Functor f => ShowFunctor f where
    smap :: (Show a, Show b) => (a -> b) -> f a -> f b
    smap f = fmap f

and then use that class instead of the original.

But maybe you don't need the additional class and for your applications it is sufficient to define smap at the top level and simply use that instead of fmap,

smap :: (Functor f, Show a, Show b) => (a -> b) -> f a -> f b
smap = fmap
like image 162
Daniel Fischer Avatar answered Nov 15 '22 11:11

Daniel Fischer


You cant do that without breaking things (currently).

You have a couple of options

  1. define your own restricted Functor class
  2. dont worry about defining a class and just define a function that does what you want
  3. use the RMonad package
  4. cheat

Actually, we now know how to allow instances to add constraints, so perhaps one day this wont be so bad, see Subcategories in Haskell for a paper that deals with almost exactly this issue. The syntax in that paper is a little different than what currently works in GHC, but basically we would like to redefine the Functor class to look like

class Functor f where
   type SubCat f :: * -> Constraint -- associated constraint
   type SubCat f = () -- default definition
   fmap :: (SubCat f a, SubCat f b) => (a -> b) -> f a -> f b
like image 27
Philip JF Avatar answered Nov 15 '22 09:11

Philip JF