[Haskell-cafe] how would this be done? type classes? existential types?

Chris Kuklewicz haskell at list.mightyreason.com
Thu Mar 16 07:40:00 EST 2006


Matthias Fischmann wrote:
> 
> hi,
> 
> this is one of those situations that always make scheme and perl
> hackers laugh at me: i have written a piece of code that is
> intuitively clear, and now i am trying to turn it into something that
> compiles.  and here it goes.
> 
> i have a type class that looks something like this:
> 
>   class Resource a where
>     resourceName      :: a -> String
>     resourceAdvance   :: a -> a
>     resourceStarved   :: a -> Bool
>     resourceSpend     :: a -> Int -> a
>     resourceEarn      :: a -> Int -> a
> 
> resource types are rice, crude oil, pizza, software code, and so on.

If there is a known list of resources, then they could all be a single data type.

> they all have a different internal structure and the same abstract
> interface, that's why i have defined this type class.
> 
> now i want to create a list of a type similar to
> 
>   [r1, r2, r3] :: (Resource a) => [a]

The above only works if r1 :: a, r2 :: a, and r3 :: a

But this is not what you want, since pizza and crude oil are different types.

> 
> but with r1 being pizza, r2 being crude oil, and so on.  my first idea
> was this:
> 
>   data Rs = forall a . (Resource a) => Rs a
>   unRs (Rs a) = a
>   rsName :: Rs -> String
>   rsName = resourceName . unRs
>   ...
> 
> and then export Rs as an abstract data type.  this would allow for
> lists of type [Rs], which is exactly what i want.
> 
> but what is the type of unRs?  or better: can i make it type at all?

No.  You cannot make unRs like that.

> and isn't this solution a little redundant and verbose?  should i do
> it like in the example for existentially quantified types in the ghc
> manual?
> 
>   http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html
> 
> but wouldnt't the code become really messy?  or should i do the type
> class and instances, and then do Rs the existentially quantified way,
> with all class methods arguments to the Rs constructor?  or is there a
> completely different way to do this (besides using scheme or perl :-)?
> 
> 
> thanks,
> matthias
> 

But you can make a list of such things:

(Why isn't it "resourceName :: String" ?)

class Resource a where
    resourceName      :: a -> String
    resourceAdvance   :: a -> a
    resourceStarved   :: a -> Bool
    resourceSpend     :: a -> Int -> a
    resourceEarn      :: a -> Int -> a

data R where { R :: Resource a => a -> R }

instance Resource R where
    resourceName (R a) = resourceName a
    resourceAdvance (R a) = R (resourceAdvance a)
    resourceStarved (R a) = resourceStarved a
    resourceSpend (R a) i = R (resourceSpend a i)
    resourceEarn (R a) i = R (resourceEarn a i)

data Pizza=Pizza
data Oil=Oil

instance Resource Pizza where
  resourceName _ = "pizza"

instance Resource Oil where
  resourceName _ = "oil"

list = [R Pizza, R Oil]

names = map resourceName list

-- 
Chris


More information about the Haskell-Cafe mailing list