Haskell Web Framework

I haven’t said much on the Haskell mailing lists, though I’ve been following them for the past few months. I’ve been using Haskell for close on a year now, and must say that I love it. What I would especially love would be to create websites in Haskell, which is where this post comes in.

Before someone jumps in with a framework suggestion of HAppS or Turbinado, they are simply not options for me (and I assume many other people) because I am stuck with shared hosting services. The only framework I’ve seen so far that seems to be shared hosting-friendly is Kibro, which- although great for its purpose I’m sure- simply does not give the features I’d be looking for in a framework.

I’m not trying to claim here that these other frameworks are The Wrong Way and that I have created a framework that does it The Right Way. So far, I have written some code, but I know that, by myself, I won’t be able to get it to handle everything that it should. I’m hoping to engage others here in some brainstorming, and perhaps ultimately collaborating on code, to design a much more complete web framework.

I have thought quite a bit about some portions of the framework, whereas for others (most notably models) I don’t have anything coherent thought out. So my idea was to throw up all my thoughts here and get people’s feedback. If you think my ideas might be a good basis for collaborating on a Haskell web framework, then we can move on from there. Otherwise, I guess I’ll return to the torture which is (PHP | Python | Ruby) coding.

  1. We should have something similar to WSGI. This way, the same application can be used running its own server (especially useful for testing), CGI, FastCGI or even mod_haskell. You can see my idea for this generic typeclass in Web.Server.Service.WebServer. I don’t have my heart set on most of that interface, except for the next item.
  2. Approot is very useful. Basically, I think every request should carry along with it the following two pieces of information: the URL to the root of the current web application, and the path to the current page within the web application. For example, if I write a web application and am running it with the test server on port 8080, and go to the URL “http://localhost:8080/foo/bar/”, the approot is “http://localhost:8080/” and the path is “foo/bar/”. This becomes very useful when you then stick your web application in a subdirectory of another site, so that the application home page is http://www.example.com/myapp/. Then if you go to http://www.example.com/myapp/foo/bar/, the approot is http://www.example.com/myapp/ and the path is foo/bar/.
  3. By convention, each web application should have a “static” directory for images, CSS, JS, etc. Then, we can automatically generate .htaccess files for (Fast)CGI versions of the site that show those files, and the built in server would know to display those.
  4. Now pulling points 2 and 3 together a little bit: there is a built in concept of internal versus external links. This might be represented as data Link = ILink String | ELink String. You could then create a function to convert the links into URLs as so: urlFromLink :: Request -> Link -> String
    urlFromLink _ (ELink s) = s
    urlFromLink req (ILink s) = approot req ++ s
    This way, the link ILink "static/images/cutecat.jpg" will turn into either http://localhost:8080/static/images/cutecat.jpg or http://www.example.com/myapp/static/images/cutecat.jpg
  5. User authentication should be built in. I like the idea of basing it around OpenID with options for logging in with e-mail addresses, and then having a built in interface for linking OpenIDs and e-mail addresses together into a single account, but I’m flexible on this point.
  6. Another flexible point: we should store session data in encrypted client cookies. I believe I read about this first with Rails 2.0, and that it is apparently supposed to be much faster since it doesn’t require file access for every request. I know that in the past I’ve been bitten by concurrent writes to SQLite databases when writing session information, and this can help.
  7. We should use UTF-8 everywhere and for everything. I suppose we should make it possible for someone to use a different encoding, but UTF-8 is the right answer 99% of the time IMHO.
  8. When it comes to models, I am torn between “let’s build a great ORM” and “relational databases are awesome.” My day job is an actuary, so I am very comfortable with straight SQL, but I understand that other people are not. There is also the issue of type safety to deal with. I defer on models to those wiser than I here.
  9. I really like the idea of generic views, though the implementation obviously depends greatly on how we do models, so I don’t have any clear ideas on this yet.
  10. The framework should handle any type of response, be it an image, a plain text file, XML, JSON or HTML. However, we should have a very high-level framework for generating interactive HTML pages that include AJAX functionality. This last piece is broken up into sub-parts, and makes up the rest of the items.
  11. I’ve always been irked by the thought of treating <head> and <body> content as the same thing. For example, most frameworks allow you to specify, somehow, a layout for other HTML pages. This layout usually looks something like this:<html> <head> <link rel='stylesheet' href='style.css'/> <title>[...]</title> </head> <body>[...]</body> </html>
    See the problem? You have to supply two separate hooks to fill in content in the template: one for the title, one for the actual content. Now, let’s say that you want one page to have an additional stylesheet, or some javascript. You need to make even more hooks available. Instead, I think that we should specify our layouts and pages in something similar to the following:
    data Tag = Tag { isHead :: Bool, name :: String, attrs :: [(String, String)], children :: [Tag] } | TagRaw String
    type Page = [Tag]

    myPageContent :: Page
    myPageContent = [Tag True “link” [(“rel”, “stylesheet”), (“href”, “mypage.css”)] [], Tag True “title” [] [TagRaw “My Page”], Tag False “h2” [] [TagRaw “My Page”]]

    layout :: Page -> Page
    layout content = [Tag True “link” [(“rel”, “stylesheet”), (“href”, “layout.css”)] [], Tag False “h1” [] [TagRaw “My Site”]] ++ content

    myPage :: Page
    myPage = layout myPageContent

  12. User input validation should Just Work. If you specify that a box should be a date, then you should automatically have client- and server-side validation of the content without having to think about it. Along the same lines, you should automatically get a date picker attached. The same theory applies to all input types. This should interact perfectly with the model portion as well.
  13. It should be possible to have the output of one piece of the page be dependent on some other part. For example, let’s say you have an input box on the page for someone’s birthday, and elsewhere an output box for their age. We should be able to simply specify the algorithm necessary to calculate an age from a birthday, and the framework will convert this into both client- and server-side code, so that if Javascript is available, the user will immediately see his/her age; otherwise, it will show up after hitting submit.
  14. Related to the previous note: sometimes it is not possible to generate these results client-side. Take, for example, a drop-down list of blog entries to choose from. If the user selects a new entry, there is no Javascript in the world that can automatically determine the content of the post without consulting the server. So I think we need something like the following: when the framework knows that the server will be consulted for some information, it will automatically generate a controller for that information in JSON format (or XML, I’m not very particular on that issue). Then, when the user selects the drop-down box, it will run an AJAX query to download the content and update the page. If javascript is unavailable, the new content will be filled in after hitting submit.

Sorry for my verbosity, but I wanted to get all these ideas into one place and open up a forum for discussion of them. Once again, if this sounds like a good idea to anyone else, and others would like to help brainstorm and implement this in Haskell, let me know. If you think this is a stupid idea, let me know that too ;-).

Advertisements

Tags: ,

6 Responses to “Haskell Web Framework”

  1. Gour Says:

    Hi!

    I’m delighted to hear about your idea to provide Django-like framework written in Haskell which could be used on shared hosting 🙂

    Atm, I’m fiddling with (nice) CMS Made Simple PHP CMS, but I do not want to go into learning PHP – I’m trying (again) to learn Haskell, this time with RWH).

    I took a look at Django any played with some basics even to the extent to decide to learn Python in order to be able to tweak it for my needs.

    However, having such framework in Haskell would be great!!

    I don’t think so that ‘framework’ in not in the spirit of Haskell…

    Otoh, if you are aware of e.g. Pinax (http://pinaxproject.com/) they strive to provide ‘framework’ for building sites out of Django-reusable-apps. Btw, there was lot of talk about ‘reusable apps’ at the latest Djangocon – building apps from clearly-defined ‘blocks’ which is, I believe, according to the Haskell spirit.

    Moreover, success of Django shows that there is still need for non-Ajax apps and I believe that shared-hosting won’t disappear over the night and all thsoe users will just run VPS-es.

    So, as conclusion, as I’m thinking that hacking on one’s web site is more fun when doing in Python/Django than in PHP, so I strongly believe that having opportunity to hack in Haskell using framework ala Django which generates lot of boilerplate code via simple scripts is great idea, and being able to use it in shared hosting makes it excellent!!! 😀

    I hope there will be enough interest amongst Haskell hackers to launch it without worrying to much just about Web 2.0 apps and stuff like Happs (great, but overkill for many).

    I already have – for quite a long time – Haskell project in mind, so if your project launches and considering that my Haskell skills improve, I’ll be able to help accordingly ’cause there won’t be need to go into learning Django 😉

    All the best!

    Sincerely,
    Gour

    Happs is defnitely overkill for lot of users and that’s wgy

  2. Gour Says:

    Hi!

    In my search for ‘light’ Haskell framework I stumbled upon hvac. Have you seen it – http://dbpatterson.com/articles/9 ?

  3. admin Says:

    hvac looks very interesting… I’m torn on whether I like using operators like this or not, but I’ll admit that this method of writing controllers is much more succinct than what I have so far.

    On the other hand, doing raw HTML output without any Javascript assistance is still. Therefore, I’m going to continue working on the code I’ve got so far. But maybe converging on the WSGI-style interface is still a possibility if any other framework authors are interested…

  4. Gour Says:

    Hi!

    Have you aroused some interest for your framework?

    You’re right – those operators are not thrilling and the code LOOKS not so grerat. 😀

    I asked today in #happs and nothing significant will change with new Happstack in regards to become more shared-hosting-friendly 😦

    Otoh, I got news that new version of CMS MS will be developed on new PHP framework, so you’re the last hope for me in order not to go to Python waters 😉

    Sincerely,
    Gour

    • Michael Snoyman Says:

      I don’t know if I’m getting interest; you’re commenting here, so that’s some interest ;). There was some talk on Haskell-cafe, but no one is jumping in to help with any code or ideas on the parts I needed help with (models, type safety in views). But I’m plowing ahead anyway.

      I’m cleaning up the code I have and putting it on github. I’m debating how many separate repositories to go into; should the backend stuff get its own, or should I just throw it all together? So far, I’ve created two repositories:

      webutils has some generic code (parsing and creating query strings, URL encoding, etc) that all web frameworks could take advantage of.
      yesod is the name of the framework. Yesod is Hebrew for “foundation,” which seems like an appropriate name to me. It doesn’t have much code in it right now; I’m migrating the code that I link to in this blog.

      My idea is to set some goals for each release. For example, release 0.0.1 should have the backend system ready with the standalone and CGI adapters. Each release should also include an example application that will demonstrate the features available. So release 0.0.1 will hopefully have a static file server/uploader web application. And due to the design, it will work seamlessly as either a standalone server or as a CGI program.

      If you’re interested in contributing, I’d say to start by making a Wiki page on the Yesod repository on Github to describe some of your ideas for the framework, in the same way that I outlined them in this post. The whole point of me asking for collaborators is so that others can save me from my own mistakes- both in design and code!

  5. Gour Says:

    I don’t know if I’m getting interest; you’re commenting here, so that’s some interest ;).

    Not many LOC is written due to my interest 😦

    There was some talk on Haskell-cafe, but no one is jumping in to help with any code or ideas on the parts I needed help with (models, type safety in views). But I’m plowing ahead anyway.

    Nice to see you’re enthusiastic despite of it.

    I’m cleaning up the code I have and putting it on github. I’m debating how many separate repositories to go into; should the backend stuff get its own, or should I just throw it all together?

    I’d throw everything together, at least in the beginning.

    yesod is the name of the framework. Yesod is Hebrew for “foundation,” which seems like an appropriate name to me.

    Nice. Is it spelled like ‘yeshod’?

    If you’re interested in contributing, I’d say to start by making a Wiki page on the Yesod repository on Github to describe some of your ideas for the framework, in the same way that I outlined them in this post.

    I believe I’m too unexperienced with both Haskell and web programming in general to put something useful together… :-/

    The whole point of me asking for collaborators is so that others can save me from my own mistakes- both in design and code!

    …but let me state few points based on my superficial experience with Django:

    1) running on shared-hosting

    I like idea of yesod running on shared hosting and as one can see from the comments on http://aftnn.org/journal/661 post “Happstack by design is not shared-host friendly. All state is kept in memory. It’s meant for scalability and high availability. Even if we supported something like fcgi the memory usage would prevent you from finding cheap hosts that support it anyways. You can get a vps from linode for 20 bucks a month.” Happstack is not meant for that.

    2) creating boilerplate code ala Django

    It’s really nice how one can get a basic skeleton of web app in Django by running few simple scripts with nicely/clearly separated functionalities (MTV)

    3) template language…

    ..in Django is simple and functional and I believe that Haskell framework can offer, at least, the same.

    4) ORM

    Based on what I read, FP & SQL should match together better than OO, although when I asked on haskell-cafe about database stuff available for Haskell, HDBC author shared his experience that higher-level libs do not offer much advantage in comparison with more lower-level lib like HDBC and I consider that asking from web-developer to be familiar with SQL is not too much.

    5) reusability

    That’s one of the ‘killer’ features of Django and lot of talk was going in Djangocon about.

    Pinax & Satchmo are two frameworks evolving based on that concept and I believe that ‘reusability’ ala Django should be possible in yesod Haskell framework by taking care to avoid ‘Haskell web frameworks reinvent too much’ syndrom (I do not want to argue how/if it is valid.)

    6) documentation

    It’s one of the ‘killer’ feature of both Django and Happs(tack) – each one taking it to the other side 😀

    It’s really encouraging to see lot of nice online docs, books etc.

    Of course, yesod is at the beginning, but lot of Haskell projects suffer a lot due to lack of decent documentation 😦

    7) community

    Django community is, based on what I experienced, really nice and Haskell has an excellent one – so yesod should take advantage of it.

    It’s a pity that Haskell is missing many potential web coders by not offering something like Django for those devs leaving PHP boat (I personally know several ones and maybe I would be one) and coming to Python due to Django (similar effect was with Ruby/Rails some time ago).

    Haskell is superior language to Python, but many people need to code to do everyday’s job on web sites running on shared hosting, so having some (framework) to offer them to hack on woul be great.

    I’ll stop my ‘rambling’ for now…Probably did not say anyting new, but I hope you’ll find some qualified man-power at this stage to keep the ball rolling.

    Sincerely,
    Gour

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: