[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