Re: [Haskell-cafe] reifying typeclasses

[I too had the problem sending this e-mail to Haskell list. I got a reply saying the message awaits moderator approval] Evan Laforge wrote:
I have a typeclass which is instantiated across a closed set of 3 types. It has an ad-hoc set of methods, and I'm not too happy with them because being a typeclass forces them to all be defined in one place, breaking modularity. A sum type, of course, wouldn't have that problem. But in other places I want the type-safety that separate types provide, and packing everything into a sum type would destroy that. So, expression problem-like, I guess.
It seems to me like I should be able to replace a typeclass with arbitrary methods with just two, to reify the type and back. This seems to work when the typeclass dispatches on an argument, but not on a return value. E.g.:
If the universe (the set of types of interest to instantiate the type class to) is closed, GADTs spring to mind immediately. See, for example, the enclosed code. It is totally unproblematic (one should remember to always write type signatures when programming with GADTs. Weird error messages otherwise ensue.) One of the most notable differences between GADT and type-class--based programming is that GADTs are closed and type classes are open (that is, new instances can be added at will). In fact, a less popular technique of implementing type classes (which has been used in some Haskell systems -- but not GHC)) is intensional type analysis, or typecase. It is quite similar to the GADT solution. The main drawback of the intensional type analysis as shown in the enclosed code is that it breaks parametricity. The constraint Eq a does not let one find out what the type 'a' is and so what other operations it may support. (Eq a) says that the type a supports (==), and does not say any more than that. OTH, Representable a tells quite a lot about type a, essentially, everything.
types. It has an ad-hoc set of methods, and I'm not too happy with them because being a typeclass forces them to all be defined in one place, breaking modularity. A sum type, of course, wouldn't have that Why not to introduce several type classes, even a type class for each method if necessary. Grouping methods under one type class is appropriate when such a grouping makes sense. Otherwise, Haskell won't lose in expressiveness if a type class could have only one method.
{-# LANGUAGE GADTs #-} module G where data TRep a where TInt :: TRep Int TChar :: TRep Char class Representable a where repr :: TRep a instance Representable Int where repr = TInt instance Representable Char where repr = TChar argument :: Representable a => a -> Int argument x = go repr x where -- For GADTs, signatures are important! go :: TRep a -> a -> Int go TInt x = x go TChar x = fromEnum x -- just the `mirror inverse' result :: Representable a => Int -> a result x = go repr x where -- For GADTs, signatures are important! go :: TRep a -> Int -> a go TInt x = x go TChar x = toEnum x t1 = argument 'a' t2 = show (result 98 :: Char)
participants (1)
-
oleg@okmij.org