[Haskell-cafe] Re: I'm stuck in my thought experiment
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. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: I'm stuck in my thought experiment
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. Layout might not actually be the right term. Page template might be better. What I'm trying to gain is best described with an example. * I have a template with a header image, and footer text. * I create another template defined as the previous, but with a menu bar down the left. * I create a page based on the previous with some text. The gain comes from when I want to change the header image, or add a Login/Register box on all pages, I only edit the first template. Levi ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: I'm stuck in my thought experiment
Al Falloon wrote: Maybe I am misunderstanding your requirements, but it seems to me that the simplest solution would be best in this case: data Widget = BlogWidget [Article] | TextWidget String | MenuWiget Menu | Rows Spacing [Widget] | Columns Spacing [Widget] You can also add a type parameter if you want to be able to carry around extra metadata about pages, or you could even parameterize the Article and Menu types if you want to be able to extend them separately or if you want to ensure your layout algorithms don't depend on widget contents by keeping their type abstract. Thanks for pointing out a simple solution. Over thinking this is something I'm worried about :) 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. 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. The issue becomes, given a parent page and the customized content for the child page, what is the best way to insert the customized content at the right point? Might a tree like structure be useful? But, how do you work out where in the tree child content gets added? Store a traversal with each sub tree of child page content that basically says 'insert here'? This is probably a good use for a zipper (a kind of functional iterator). http://en.wikibooks.org/wiki/Haskell/Zippers that way you can pass around a value that means right here, and its clear where the substitution will happen. I was wondering with zippers were appropriate, or if I just had them in mind becuase I'd read so much about them lately :) 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 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 Thanks Levi lstephen.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: I'm stuck in my thought experiment
Levi Stephen wrote: Hi, Apologies for a long post that may not be totally clear. I was thinking through a problem and how the data might be represented in Haskell. I'm now stuck and frustrated. Now, I'm not even sure whether I'm on the right track (I might still be thinking too OO). Suggestions/ideas would be much appreciated. 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. Along with these are layout/container widgets (e.g., ColumnLayoutWidget) that can contain other widgets. I'm looking at a data structure that would allow this to be represented in Haskell, so I'm keeping in mind that these won't be written in code, but generated on the fly somehow (e.g., from a database or file). Maybe I am misunderstanding your requirements, but it seems to me that the simplest solution would be best in this case: data Widget = BlogWidget [Article] | TextWidget String | MenuWiget Menu | Rows Spacing [Widget] | Columns Spacing [Widget] You can also add a type parameter if you want to be able to carry around extra metadata about pages, or you could even parameterize the Article and Menu types if you want to be able to extend them separately or if you want to ensure your layout algorithms don't depend on widget contents by keeping their type abstract. So, my thoughts were along the lines of something like: 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 data TextWidget = TextWidget String instance Widget TextWidget -- An example layout widget data ColumnLayoutWidget = ColumnLayoutWidget [Widget] instance Widget ColumnLayoutWidget ... etc... So, entire pages might be represented something like: Page Main (ColumnLayoutWidget [MenuWidget, TextWidget mainPageText]) Page About (ColumnLayoutWidget [MenuWidget, TextWidget aboutPageText]) 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. 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. 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 Where I get stuck, is I want to extract layout information into a parent page. This would allow global changes such as adding a header image to the above pages to be done once only. By making the layout type separate from the widgets themselves, it allows you to examine the layout and do any transformations you want without having to know anything about the widgets. So I want to be able to have something like: layout = Page Main (ColumnLayoutWidget [MenuWidget, ??? ]) mainPage = ChildPage layout [TextWidget mainPageText] aboutPage = ChildPage layout [TextWidget aboutPageText] So, each page is it's layout/parent page, with additional widgets inserted/added. 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. The issue becomes, given a parent page and the customized content for the child page, what is the best way to insert the customized content at the right point? Might a tree like structure be useful? But, how do you work out where in the tree child content gets added? Store a traversal with each sub tree of child page content that basically says 'insert here'? This is probably a good use for a zipper (a kind of functional iterator). http://en.wikibooks.org/wiki/Haskell/Zippers that way you can pass around a value that means right here, and its clear where the substitution will happen. Another good zipper war story is from xmonad: http://cgi.cse.unsw.edu.au/~dons/blog/2007/05/17 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