[Haskell-cafe] I'm stuck in my thought experiment

Matthew Brecknell haskell at brecknell.org
Thu Aug 16 21:45:15 EDT 2007

Levi Stephen:
> [...]
> I was imagining a drag and drop web page designer. There are a bunch of
> Widgets (e.g., BlogWidget, TextWidget, MenuWidget, etc) that the user can
> place on the page.
> [...]
> class Widget a where
>   render :: a -> Html
> -- A page has a title and a Widget.
> -- I know this isn't valid Haskell, but I'm not sure how to specify what I
> -- want here. (existential types?)
> data Page = Page String Widget

If you wanted to make Page an existential type, it would look like this:

data Page = forall w . Widget w => Page String w

However, you will probably find it much more useful to define a single
existential wrapper for all widgets:

data WidgetW = forall w . Widget w => WidgetW w

Then, for example, you can construct polymorphic lists of widgets, as is
necessary for the column layout:

data Columns = Columns [WidgetW] -- hmm, needs spacing info.

And now Page just adds a string to a WidgetW:

data Page = Page String WidgetW

See the GHC users guide for more on how to use existential types.

> [...]

> layout = Page "Main" (ColumnLayoutWidget [MenuWidget, ??? ])
> mainPage = ChildPage layout [TextWidget mainPageText]
> aboutPage = ChildPage layout [TextWidget aboutPageText]

Layout just looks like a function. Assuming an existing global menu

layout ws = WidgetW (Page "Main" (WidgetW (Columns (menu : ws))))

Note the type of layout: a function taking a list of widgets and
returning a single widget. You'll find a number of similar types useful
for structuring your code. For example, functions taking a single widget
and returning a single (more complex) widget, functions taking a single
widget and a list of functions each taking a widget and returning a
widget, and returning a list of widgets, and so on. It's called
functional programming for a reason. :-)

> This just gets trickier if I start considering multiple extension points
> for child pages and what happens when the layout/parent page changes.
> This is why I'm thinking I may be going along a bad path here.

Indeed, abstractions of this kind usually require a fair amount of
thought and experiment. I haven't given it either of these, but
hopefully the suggestions will help you become less stuck.

More information about the Haskell-Cafe mailing list