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

Al Falloon afalloon at synopsys.com
Tue Aug 21 09:31:16 EDT 2007


Levi Stephen wrote:
> Al Falloon wrote:
>> This code seems to indicate that you want to be able to extend the 
>> widget types without changing this source file. This is a good goal, 
>> but it may not be worth the extra complexity.
> 
> Ideally, I'd like Widgets to be added through hs-plugins or similar. That
> is a ideal goal though, not a necessity.

>> Also, this looks a lot like the Composite pattern from OO. A rule of 
>> thumb that I use is: "if I would do this with inheritance in OO, I 
>> probably want a variant in FP". Since Composite depends on the 
>> inheritance of the composite object type, I would probably look to use 
>> a  single data type with multiple constructors for the different 
>> compisites like the Widget type above.
> 
> Interesting. I've been curious how OO concepts can map to FP, as most specs
> (consider stuff like DOM) seem to be written with OO implementaitons in 
> mind.

This is a very interesting discussion that could be its own text book 
(or flame war) as far as I can tell, the only answer everyone agrres on 
is "it depends". After that it gets a little hairy.

For me, I find that the best method is to just come at the problem fresh 
using an FP approach, and don't worry about 'mapping' the concepts.

>> If I wanted to develop the widgets themselves separately from the 
>> layout, I would probably do something like this:
>>
>> class Widget a where
>>     render :: a -> Html
>>     bbox :: a -> Size
>>
>> type Layout = forall a. Widget a => Widget a
>>     | Rows Spacing [Layout]
>>     | Columns Spacing [Layout]
>>     | Grid Spacing [[Layout]]
>>
>> type Page = Page String Layout
>>
>> renderLayout :: Layout -> Html
>>
>> renderPage :: Page -> Html
> 
> I'm unsure this gives what I'm after. I'm trying to have layouts consist 
> of Widgets (e.g., header images, common menu), and as pages also consist 
> of Widgets it seems like they can be modelled using a common 
> type/construct.

Well if you want to abstract over the layout too, you can just add

instance Widget Layout where
	render = renderLayout
	bbox = ...

But just because you can, doesn't mean you should. I don't know the full 
details of your design, but what do you gain by allowing the layout to 
intermingle with the widgets? Is worth the extra complexity?

If you treat layout as "just another widget" then it becomes harder to 
answer specific questions about the page layout because you have less 
information in your tree.

>> So you want some sort of wildcard element that can be substituted in
>> later? Maybe I am misunderstanding your requirement, but if thats the
>> behavior you want, you should check out the term-level evaluators for
>> lambda calculus for inspiration on substitution, but I expect your
>> requirement may be simpler than that.
> 
> I'm thinking a BlankWidget or ReplacableWidget is a fairly simple 
> option. They could be named for the case of multiple replacements, and 
> have a method similar to
> 
> --                 src   ->   replacements    -> result
> replaceWidgets :: Widget -> [(String,Widget)] -> Widget
> 
> which replaces all ReplacableWidgets in the source Widget with those 
> specified.
> 
> Would you happen to have some links on the evaluators for lambda 
> calculus you talk about? I'm not as familiar as I should be with lambda 
> calculus

They are surprisingly hard to find! It must be one of those things that 
is so ingrained that no-one thinks to write it down. Anyway, the closest 
I could find to what I meant is the "Interpretive Haskell programmer" 
heading in "The evolution of a Haskell programmer" 
http://www.willamette.edu/~fruehr/haskell/evolution.hs

However, now that I look at your example again, I may have been too 
quick to answer with "LC evaluator!" because your language only has 
substitution and not abstraction (defining functions) so you don't have 
much of the complexity to contend with.

The obvious implementation of replaceWidgets will probably work fine for 
you.


>>> It might be simple to have a PlaceHolderWidget. Then insertions of 
>>> the child page
>>> content happens at each of those widgets.
>>
>>> 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.
>>
>> Exactly. With multiple substitutions you get into issues of naming, so 
>> thats why looking at lambda calculus evaluators would be the right 
>> inspiration, but I think it may be more complicated than you need. The 
>> zipper approach might be easier.
> 
> I think I will try and investigate both approaches. I'm after the 
> process here, rather than the end result

Good luck.

You can learn a lot just by lurking on the cafe and reading some of the 
better blogs. The papers are also good reading, I have a "rule of 2" if 
I have heard the title come up twice, I read it.



More information about the Haskell-Cafe mailing list