Archive for July, 2006
How easy is it to write an AJAX
application in Haskell? Very easy
indeed. Here’s a little example of an AJAX server that echoes
JSON requests:
module Main where
import Data.Maybe (fromJust)
import JSON
import Network.NewCGI
jsonEcho :: CGI CGIResult
jsonEcho = do jsonString <- getInput "json"
setHeader "Content-type" "application/x-javascript"
output $ (stringify . fromJust . parse . fromJust) jsonString
main = runCGI jsonEcho
To get this to compile you need the following haskell libraries: Fast
Packed Strings (needed by
haskell-cgi), XHTML
combinators (needed
by haskell-cgi),
haskell-cgi,
and JSON.hs
The resulting executable can be installed on any web server that
supports cgi scripts. For my tests I configured apache with cgi
execution enabled in user directories. You can download the little
example app here. The client code employs the
json and
prototype Javascript libraries.
The JSON.hs file included in this distribution is a slightly modified
version of the one listed above which adds support for Ints.
July 13th, 2006
matthias
I have been trying to get some real work done with Haskell - shock, horror! As part of that I am using the excellent HaskellDB combinator library for type-safe and composable database operations. HaskellDB employs some advanced type constructs such as phantom types, which can result in rather complex types that make analyis of type errors a bit of a challenge. It also makes it tricky to produce type annotations for the code by hand, e.g. for documentation purposes. One can of course ask haskell for the type, and then just stick that in the annotation, but the types one gets this way do not make for pleasent reading and require exposure of a whole bunch of HaskellDB’s typing guts.
By far the most weird typing issue I ran into though is when I had two identical (in all but name) functions, one of which was being used in my code and the
other one wasn’t:
intervalIds = map $ flip (!) TaskTime.xid -- used
intervalIds' = map $ flip (!) TaskTime.xid -- not used
The type checker chokes on the latter with
No instance for (Select (Attr Task_time.Id Int) a a1)
arising from use of `!' at Model.hs:59:26-28
Probable fix:
add an instance declaration for (Select (Attr Task_time.Id Int)
a
a1)
In the first argument of `flip', namely `(!)'
In the second argument of `($)', namely `flip (!) Task_time.xid'
In the definition of `intervalIds'':
intervalIds' = map $ (flip (!) Task_time.xid)
So it looks like the use of intervalIds places sufficient constraints on the typing to make the function typable, and the absence of such constraints for intervalIds' results in an untypable expression.
On reflection this is not really surprising. A number of the advanced typing features of haskell are not amenable to type inference and hence require explicit type annotations. However, as explained above, coming up with these annotations is not always easy or desirable.
July 7th, 2006
matthias
I recently used wicket to knock up a simple web shop example for our ExproRetail product and found it to be a fairly pleasant experience.
Wicket is (yet another) Java web framework but it distinguishes itself from many others with the following features:
- No XML configuration
- Very clean page templates
- High level of abstraction - User code rarely has to refer to HTTP concepts
Writing a Wicket app is rather more like writing an event-based desktop application than a web application. For example, to render a link and react when it’s clicked all that’s needed is:
In the template:
<a wicket:id="mylink">Click me</a>
In the code:
add(new Link("mylink") {
public void onClick() {
// Do something when link clicked...
}
});
Similarly, to handle a form submission you could create a TextField, give it a model to read/write its data to and add it to a Form. In either case there is no need to worry about constructing specific URLs, query parameters, HTML escaping etc.
Templates are just standard XHTML with a sprinkling of wicket attributes. When Wicket renders the template and encounters a wicket:id it looks for a matching component to render the tagged element. This is a simple and powerful system very similar to that used by the Python web kit nevow.
Wicket also makes it very easy to create custom “widgets”: Simply extend from an appropriate subclass of Component and provide a snippet of XHTML (if needed). To use your widget, all that’s needed is a simple add(new YourComponent(...)).
With version 1.2 there’s lots of AJAXy goodness too but I’ve yet to try this myself and the docs seem to be slipping behind a little.
The downside to all this convenience, at least for any reasonably busy site, is that Wicket stores a lot of state in user sessions. Some of the time gained letting Wicket manage everything may be lost ensuring that session usage is kept under control.
July 6th, 2006
mporter
Unlike traditional website visitors, most readers of a blog use a news
aggregator to periodically pull new items from the blog’s syndication
feed. As a result, the co-relation between the number of requests and the number of
times an item is read is broken, and to confuse things even more - many
readers use a public aggregator service which saves the feed to a
central repository and serves the saved entries to many readers. For such
services, growth in the number of subscribers is not represented by an
increase in the number of requests made.
To get a rough estimate of the number of subscribers to a feed we need
to separate between requests made by public services on behalf of more
than one user, and requests made by individual news
aggregators.
If you too are curious about the number of subscribers to your blog
(and have access to the HTTP access log of the server hosting it) you
can give my little script, Blogalizer,
a try.
Continue Reading July 4th, 2006
Tom Berger
I wanted to define equality functions for unit testing purposes. The general pattern is that I’ll call a method that returns a complex data structure. I’ll want to test if the data structure matches the sample data structure in my test. Frequently the definition of Object.equals() won’t test equality in the way I wants to - it will depend on identity. I’ve defined an equality function that generally provides what I need, and can be easily specialised. There are quite a few things to consider, so I thought I’d write this article about it.
Continue Reading July 4th, 2006
david
Next Posts