Terrance Niechciol
Terrance Niechciol

Reputation: 250

Haskell - List of instances of a Typeclass

I'm fairly new to Haskell, and to get better I'm trying to make a simple web server. I wanted to make how I represent pages extendable, so my idea was to make webpages be a list of Renderable data (like how you can make a list of objects that implement a certain interface in Java) where Renderable is

class Renderable a where
    render :: a -> IO String

Unfortunately I learned that lists MUST be a concrete type, so I can only make a list of one type of Renderable data. Also it seems impossible to create data that is constrained by a typeclass, so I can't make something like RenderList data. My temporary solution has been like this:

myPage =
    [render $ someData
    ,render $ someMoreData
    ,render $ someOtherData
    ...
    ]

but this feels awkward, makes the use of a typeclass have no benefit, and feels like there should be a better way. So I'm wondering what ways could I restructure what I have to be cleaner, more in line with standard Haskell practices, and still be easily extendable?

Thanks.

Upvotes: 15

Views: 4954

Answers (2)

mergeconflict
mergeconflict

Reputation: 8266

You're trying to implement an object-oriented style of design. In Java, for example, you'd have a List<Renderable> and you'd be all set. This design style is a little bit less natural in Haskell; you need to create a wrapper type for a bounded existential as demonstrated on the Haskell wiki page for existential types. For example:

class Renderable_ a where
  render :: a -> IO String

data Renderable = forall a. Renderable_ a => Renderable a
instance Renderable_ Renderable where
  render (Renderable a) = render a

You can then have a list of Renderable, which you can render however you like. Like I said, though, that is sort of an OO style which is less natural in Haskell. You can probably avoid this by rethinking your data structures. You say that you "wanted to make how you represent pages extendable"; consider other ways of doing that instead.

Unrelated: I'm guessing render doesn't need to produce an IO String action. Try to keep IO out of the core of your design, if you can.

Upvotes: 13

horsh
horsh

Reputation: 2779

Check out this page on haskell heterogenous collections. It provides ideas of several approaches.

Upvotes: 5

Related Questions