Question about use of | in a class declaration

Hal Daume III hdaume@ISI.EDU
Wed, 21 Aug 2002 07:39:29 -0700 (PDT)


This is a functional dependency.  You can probably find informationin the
GHC docs.  It's a way of telling the compiler how to derive type
information on multiparameter classes.  For example, if I have a class:

  class C a b where
    f :: a -> b

the type of f is

  (C a b) => a -> b

The problem here is that you may have multiple instances of C with the
same a:

  instance C Int Bool ...
  instance C Int Char ...

so when you use f, it doesn't know which instance to use.  Writing 'a ->
b' means "a uniquely determines b" and makes it so for any given a, you
can only have one instance of C, so the two above instances would be
rejected: you could only have one.

This means that when you write 'f (5::Int)' it knows which instance to
choose, since there can only be one.

 - Hal

--
Hal Daume III

 "Computer science is no more about computers    | hdaume@isi.edu
  than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume

On Wed, 21 Aug 2002, Guest, Simon wrote:

> Hello all,
> 
> Please could someone explain the meaning of | in this class declaration (from Andrew's example):
> 
> 	class (Ord k) => Map m k v | m -> k v where
> 	  lookupM :: m -> k -> Maybe v
> 
> I couldn't find reference to this in any of my standard Haskell tutorials, nor the Haskell 98 report.  Any references?
> 
> cheers,
> Simon
> 
> -----Original Message-----
> From: Andrew J Bromage [mailto:ajb@spamcop.net]
> Sent: 21 August 2002 04:19
> To: haskell-cafe@haskell.org
> Subject: Re: Question about sets
> 
> 
> G'day all.
> 
> On Tue, Aug 20, 2002 at 10:57:36AM -0700, Hal Daume III wrote:
> 
> > Lists with arbitrary
> > elements are possible, but not very useful.  After all, what could you do
> > with them?
> 
> It's often useful to have containers of arbitrary _constrained_ types,
> because then you can do something with them.  For example, given the
> class of partial mappings on orderable keys:
> 
> 	class (Ord k) => Map m k v | m -> k v where
> 	  lookupM :: m -> k -> Maybe v
> 
> 
> 	instance (Ord k) => Map (FiniteMap k v) k v where
> 	  lookupM = lookupFM
> 
> 	instance (Ord k) => Map [(k,v)] k v where
> 	  lookupM m k = case [ v | (k',v) <- m, k == k' ] of
> 	                    []    -> Nothing
> 	                    (v:_) -> Just v
> 
> 	instance (Ord k) => Map (k -> Maybe v) k v where
> 	  lookupM       = id
> 
> You can make a list of elements, which can be any type so long as
> they are a member of that class:
> 
> 	data MAP k v = forall m. (Map m k v) => MAP m
> 
> 	type ListOfMap k v = [MAP k v]
> 
> Then you can do things with it:
> 
> 	lookupLom :: (Ord k) => ListOfMap k v -> k -> [ Maybe v ]
> 	lookupLom xs k = [ lookupM a k | MAP a <- xs ]
> 
> 	test :: [Maybe Int]
> 	test
> 	  = lookupLom maps 1
> 	  where
> 	    maps = [ MAP finiteMap, MAP assocListMap, MAP functionMap ]
> 	    finiteMap = listToFM [(1,2)]
> 	    assocListMap = [(1,3)]
> 	    functionMap = \k -> if k == 1 then Just 4 else Nothing
> 
> It's a little unfortunate that you have to introduce the MAP type here.
> You can in fact construct a list of this type:
> 
> 	type ListOfMap k v = [ forall m. (Map m k v) => m ]
> 
> But then you can't use the elements in the list because the Haskell
> type checker can't find the (Map m k v) constraint.
> 
> Cheers,
> Andrew Bromage
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>