[Haskell-cafe] Restricted categories

Sjoerd Visscher sjoerd at w3future.com
Sat Feb 20 13:29:09 EST 2010


Hi all,

I want restricted categories, just like the rmonad package provides restricted monads. The ultimate goal is to have a product category: http://en.wikipedia.org/wiki/Product_category

> {-# LANGUAGE TypeOperators, TypeFamilies, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, ScopedTypeVariables, UndecidableInstances #-}

> import Prelude hiding ((.), id, fst, snd)
> import qualified Prelude

First lets create a clone of Data.Suitable from the rmonad package, but this time for types with two arguments:

> class Suitable2 m a b where
>    data Constraints m a b
>    constraints :: m a b -> Constraints m a b

> withResConstraints :: forall m a b. Suitable2 m a b => (Constraints m a b -> m a b) -> m a b
> withResConstraints f = f (constraints undefined :: Constraints m a b)

> withConstraintsOf :: Suitable2 m a b => m a b -> (Constraints m a b -> k) -> k
> withConstraintsOf v f = f (constraints v)

Now we can define a restricted category:

> class RCategory (~>) where
>   id :: Suitable2 (~>) a a => a ~> a
>   (.) :: (Suitable2 (~>) b c, Suitable2 (~>) a b, Suitable2 (~>) a c) => b ~> c -> a ~> b -> a ~> c

(->) (or "Hask") is an instance of this class:

> instance Suitable2 (->) a b where
>   data Constraints (->) a b = HaskConstraints
>   constraints _ = HaskConstraints

> instance RCategory (->) where
>   id = Prelude.id
>   (.) = (Prelude..)

Now on to the product category. Objects of the product category are types that are an instance of IsProduct:

> class IsProduct p where
>   type Fst p :: *
>   type Snd p :: *
>   fst :: p -> Fst p
>   snd :: p -> Snd p

For example:

> instance IsProduct (a, b) where
>   type Fst (a, b) = a
>   type Snd (a, b) = b
>   fst = Prelude.fst
>   snd = Prelude.snd

Arrows from the product of category c1 and category c2 are a pair of arrows, one from c1 and one from c2:

> data (c1 :***: c2) a b = c1 (Fst a) (Fst b) :***: c2 (Snd a) (Snd b)

The instance for Suitable2 restricts objects to IsProduct, and requires the Fst and Snd parts of the objects to be suitable in c1 resp. c2:

> instance (IsProduct a, IsProduct b, Suitable2 c1 (Fst a) (Fst b), Suitable2 c2 (Snd a) (Snd b)) => Suitable2 (c1 :***: c2) a b where
>   data Constraints (c1 :***: c2) a b = (IsProduct a, IsProduct b, Suitable2 c1 (Fst a) (Fst b), Suitable2 c2 (Snd a) (Snd b)) => ProdConstraints
>   constraints _ = ProdConstraints

Finally the RCategory instance:

> instance (RCategory c1, RCategory c2) => RCategory (c1 :***: c2) where
>   id = withResConstraints $ \ProdConstraints -> id :***: id
>   -- f@(f1 :***: f2) . g@(g1 :***: g2) = 
>   --   withResConstraints $ \ProdConstraints -> 
>   --   withConstraintsOf f $ \ProdConstraints -> 
>   --   withConstraintsOf g $ \ProdConstraints -> 
>   --   (f1 . g1) :***: (f2 . g2)

Here I am running into problems. I get this error:

    Could not deduce (Suitable2 c2 (Snd a) (Snd b),
                      Suitable2 c1 (Fst a) (Fst b))
      from the context (IsProduct b,
                        IsProduct c,
                        Suitable2 c1 (Fst b) (Fst c),
                        Suitable2 c2 (Snd b) (Snd c))
      arising from a use of `withConstraintsOf'
    In the first argument of `($)', namely `withConstraintsOf g'

I don't understand this, as I thought the constraints the error is complaining about is just what withConstraintsOf g should provide.
I guess there's something about the Suitable trick that I don't understand, or possibly the type families Fst and Snd are biting me.

Who can help me out? Thanks.

greetings,
Sjoerd


More information about the Haskell-Cafe mailing list