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
>