Alson Kemp

A Plea For “cabal install”

Written by alson

December 26th, 2008 at 4:43 pm

Posted in Haskell,Turbinado

Tagged with , , ,

Bookmark and Share

Updated per Ganesh’s comments.

Over here, Adolfo commented:

“Hi,I tried to do follow the example, but I couldn’t even install the packages, hsx and hs-plugins were impossible. I tried with cabal and manually, and neither of those worked . any suggestion, known issue with this packages?”

I’ve been busy adding features to Turbinado and haven’t circled back around to making sure that it’s easy to build, so I can claim a lot of the blame for the build problems.  Turns out to be really important that publicly released packages are easily buildable…

Thinking back, I have really struggled to build Turbinado… and I wrote Turbinado!  Turbinado depends on some particular bugfix-ish library releases (e.g. GSomething 0.6.1). With GHC 6.10, a bunch of libraries have broken or have changed so much that they badly break Turbinado. (I need to specify better the versions in turbinado.cabal.)

At times, I’ve considered bundling the dependencies into Turbinado so that building Turbinado would be easy, but that’s always felt like a cop-out. So I’m pleading for “cabal install”. Given Turbinado’s dependence on particular versions of libraries, I would love to able to do:

cabal install turbinado
  OR  (from /home/alson/turbinado)
cabal build

Cabal Install

Most casual users of Ruby, Python, Perl, Java, etc, know that those languages have automagic build/dependencies system (respectively, gem, eggs, CPAN, maven). The tools may be of varying quality, but many tutorials include something like “First, use GEM to install the package: gem install rails” and demonstrate just how simple it is to get a useful piece of software installed.

This is not the case in Haskell. I’d guess that no more than 5% of Haskellers know about the cabal command line tool and “cabal install”. On the other hand, I’d guess that 95% of novice Rubyers know about “gem install”. These automated build/dependency system are now critical to the success of languages. As a beginner in Ruby, I always knew that I could easily try out various libraries by using GEM to install bits of software. I’m now fairly experienced with Haskell and, partly because of that experience, I don’t believe that I can easily try out various Haskell libraries.

Niklas Broberg’s HSP is a great example of the challenge of building Haskell programs. HSP is very nicely separated into modular libraries which: makes it easy to apply pieces of HSP’s functionality to a program; makes it hard for a human (at least for me) to build any one part of HSP because each part depends on so many other parts. A build/dependency tool would make HSP much easier to build into existing programs.

The Plea

I love using Haskell and Haskell will only get better if more people are able to use it. IMO, a pre-condition to the growth of the language is a solid, easy to use build/dependency system. Cabal is that system for GHC and the cabal command line tool is a key part of that system.

Unfortunately, the cabal command line tool isn’t bundled with GHC, but … Please get it, build it, use it, report any bugs, compliment the Cabal team, etc. It’ll be a great help to the Haskell community.

darcs get http://darcs.haskell.org/cabal-install
cd cabal-install
sh bootstrap.sh

Update: Haskell Platform

Ganesh points out the Haskell Platform Proposal, so it looks as though there is a plan to incorporate the cabal command line tool. See the following:



P.S. Anyone know if the cabal command line tool is going to make it into GHC?

Links to cabal install information:




with 13 comments

Cyptol on Slashdot

Written by alson

December 26th, 2008 at 4:02 pm

Posted in Haskell

Bookmark and Share

First Haskell-ish post I’ve seen on Slashdot in a while:

Cryptol, Language of Cryptography, Now Available To the Public

Maybe I’m old school, but getting through the moderation on Slashdot seems like a big deal… Congrats to the Galois team!

without comments

Turbinado: Implementing a poor-man’s wiki

Written by alson

December 20th, 2008 at 8:08 pm

Posted in Haskell,Turbinado

Bookmark and Share

*Updated* to reflect modifications to the ORM (No “Model” suffix; fractured in Types, Functions, Relations)

These are very early days for Turbinado, so much change is going on… But here’s a quick tutorial on putting together a poor man’s page editor/manager in Turbinado.

### Build Turbinado
*Warning!*: With 6.10’s changes in dynamic plugins, Turbinado only builds with GHC 6.8 right now. Fixing this is next up in the dev queue.

You’ll need to have the following packages installed to have a go at installation:

GHC 6.8 *(darcs)*
haskell-src-exts *(darcs)*
harp *(darcs)*
hslogger *(git)*
encoding *(darcs)*
hsx *(darcs)*
hs-plugins *(darcs)*
http *(darcs)*
HDBC *(git)*
HDBC-PostgreSQL *(git)*

**Grab the code**

git clone git://github.com/alsonkemp/turbinado.git

**Build it**

With all of the packages installed, wait for a new moon, stand on tip-toes, and do the following:

runghc Setup.lhs configure
runghc Setup.lhs build

### Configure It

cp Config/App.hs.sample     Config/App.hs
cp Config/Routes.hs.sample Config/Routes.hs

Edit App.hs and Routes.hs to taste.

### Create the Page table

    title character varying NOT NULL,
    content text NOT NULL,
    _id character varying(255) NOT NULL PRIMARY KEY,

Updated: added PRIMARY KEY which is needed by the ORM generator.
### Generate the ORM models

runghc scripts/GenerateModels

You should now have an interesting file or two in App/Models.  The files are organized as follows:
* App/Models/Bases/Comment.hs – all base Models inherit this.
* App/Models/Bases/AbcXyzType.hs – the representation of the database table *abc_xyz*. Don’t edit this! It’s autogenerated and your changes will get ignored on the next gen.
* App/Models/Bases/AbcXyzFunctions.hs – CRUD functions on *abc_xyz*. Don’t edit this! It’s autogenerated and your changes will get ignored on the next gen.
* App/Models/Bases/AbcXyzRelations.hs – functions on tables related to *abc_xyz*. Don’t edit this! It’s autogenerated and your changes will get ignored on the next gen.
* App/Models/AbcXyz.hs – the user configurable area of the AbcXyz. By default this just imports the above three tables. All of your custom *find*, *insert* and *update* methods go here.

A big shout out to .netTiers for pointing the way on building a code-generator ORM.

### Create your Layout
Just as in Rails, the Layout usually defines the majority of your sites page structure. See here for the Layout used for turbinado.org.

### Create your Page controller
The controller handles the request and sets up ViewData for the View to render/display. This little Page controller has the following functions/methods/actions:

  • index: list all Pages.
  • show: render one Page.
  • new: display a blank Page form.
  • create: take the submission of the ‘new’ action.
  • edit: display an existing Page in a form for editing.
  • save: take the submission of the ‘edit’ action.

Full version here. Here’s a snippet:

-- 'id' is an important function name in Haskell, so I use id' for the Page's "id".  There's got
-- to be a better solution

-- This is the generated ORM for the 'page' table in the database.
import qualified App.Models.Page

-- Index lists out all of the pages
-- setViewDataValue is used to store data for retrieval by the View.  Idea lifted from ASP.NET 
-- http://msdn.microsoft.com/en-us/magazine/cc337884.aspx
index :: Controller ()
index  = do pages <- App.Models.Page.findAll --use ORM goodness to get all pages
            setViewDataValue "pages-list" $ map (\p -> (title p, _id p)) pages

-- Show shows one page
-- Notes:
--  * The "id" is parsed from the request's path and put into the Settings.
--     See: http://github.com/alsonkemp/turbinado-website/tree/master/Config/Routes.hs
--  * getSetting returns a "Maybe a".  getSetting_u is the unsafe version and returns just the "a".
show :: Controller ()
show  = do id'  <- getSetting_u "id"
           p <- App.Models.Page.find id'
           setViewDataValue "page-title" (title p)
           setViewDataValue "page-content" (content p)

-- snip --

save :: Controller ()
save = do   id'  <- getSetting_u "id"
            _title   <- getParam_u "title"
            _content <- getParam_u "content"
            p <- App.Models.Page.find id'
            App.Models.Page.update p {title = _title, content = _content}
            redirectTo $ "/Page/Show/" ++ id'

### Create Your Views
This Controller requires 4 views:

* Index
* Show
* New
* Edit – this could probably be the same as New.

See here for pre-built views. Here’s the “Index” view (note: *this isn’t very sugary and that makes me **sad** *):

page =  <div>
            Page Index
          <% do ls <- getViewDataValue_u "pages-list" :: View [(String, String)]
                mapM indexItem ls

-- fugly, but I'm still getting used to HSP-like templating
indexItem (t,i) = return $ cdata $ unlines $
                   ["<div style='padding: 0pt 5px;'>"
                   ," <a href=\"/Page/Show/" ++ i ++"\">"
                   ,"  "++ t
                   ," </a>"

Here’s the “Show” view and it’s *pretty sugary*:

page = <div>
          <h1><% getViewDataValue_u "page-title" :: View String %></h1>
          <% getViewDataValue_u "page-content" :: View String %>

### Run It
Start up Turbinado:

dist/build/turbinado/turbinado -p 1111

Browse to it: http://localhost:1111/Page/Index (it’ll take a couple of seconds to compile the Model, Controller and View)

### Examples!
There’s still lots of work to do on the ORM and on Documentation. As the code base matures, both should progress. Examples are a nice way to drive development forward and to engage the community, so let me know if you’d like to see anything in particular demonstrated and I’ll try to implement it.

with 18 comments

Turbinado update

Written by alson

December 18th, 2008 at 2:13 pm

Posted in Geekery,Haskell,Programming,Turbinado

Bookmark and Share

Turbinado Logo For those of you interested in Turbinado, here’s a quick status update:

  • I separated the code for the turbinado.org website from the code for the framework.  The framework is here and the website code is here.
  • I’m going to finish up implementing HAML templating for Turbinado in the next few days.
  • After HAML templates are in, I’ll provide a tutorial on implementing a mini-CMS/wiki in Turbinado (the code is already in the website.  The standard-Rails-ish “look, Mom!  No code!” type of tutorial.  Just enough to convince you to download it, but not enough to get you to be significantly productive.  😉
  • Adam Stark is providing some greatly needed polish here as he attempts to get this beastie to build.  Turbinado really needs to be easier to build…
  • Diego Echeverri is doing some work to get Turbinado to work with GHC 6.10 here. I had a difficult time getting my HSP-ish View templates working with 6.10, so I hope Diego can do it. I’d greatly prefer to be working with 6.10, but I couldn’t get there…

Writing a little web framework turns out to be a lot of work (it’s all the little stuff (documentation!!) that really gets ya).  I’ve greatly appreciated the ability to build on the work of others (especially Niklas Broberg, Don Stewart, Bjorn Bringert and John Goerzen) and am grateful that others are providing help to this fledgling project.

with 2 comments

GitHub, ‘git’ and the forking fallacy

Written by alson

December 18th, 2008 at 1:04 am

Posted in Geekery,Haskell,Programming

Bookmark and Share

GitHub is a pretty sweet system. One of the best aspects of _web 2.0_ has been the focus on simple, straightforward web app usability/utility.  GitHub is a great example of some of _web 2.0’s_ best attributes: a really interesting model coupled with straightforward usability and _just a touch_ of AJAX.  I never would have tried Git without GitHub.

Git is pretty interesting, too. Turns out that git is effective at encouraging social involvement in coding. The Turbinado project has been forked a few times… ‘Forked’?! Wait! That’s what happens when projects are in deep trouble, right?!

Maybe so, but not necessarily in git. Since git is a decentralized revision control system (like our beloved darcs), ‘forking’ is roughly equivalent to ‘checking out’. A ‘fork’ is a good thing, so Rails’ fork count (**398**) is **heroic**.

with 3 comments

Thinking About Haskell*: You Know Lazy Evaluation; You Just Don’t Know It

Written by alson

December 16th, 2008 at 1:33 am

Posted in Geekery,Haskell,Programming

Tagged with

Bookmark and Share

[Post updated to reflect comments. …too much late night typing…]
Lazy evaluation is a very novel aspect of Haskell. Turns out that it’s not that difficult to think about.

A very common example of lazy-ish evaluation is ‘&&’ operators used in lots of languages (using C#):

if ( (obj != null) && (obj.someMethod() == somethingElse) ) {
  // do something

Read the rest of this entry »

with 15 comments

A HAML parser for Haskell

Written by alson

December 11th, 2008 at 1:56 am

Posted in Geekery,Programming

Tagged with , ,

Bookmark and Share

HAML‘s lovely. As I’ve been working with Turbinado, I’ve been having some issues with HSP. HSP is an insanely impressive piece of software, but its error messages can be a bit unclear. So I started playing around a bit with HAML. Got me wondering “How easy would be to write a HAML parser in Haskell?”

So I tried. Here’s a first-pass, to-be-updated [and somewhat incomplete] HAML parser for Haskell. Not all of the features are implemented, but it’s a start.  It generates HTML bits suitable for compilation by GHC.


f = content

page = #content
         %h2 Welcome to our site!
         %p = print_information
           = print_inline
           = render
         [abba = ding, ding = abba] dinger


f =
    (stringToHtml "content")
page =
       ((tag "div"![strAttr "id" "content"])
         ((tag "div"![strAttr "class" "left column"])
         ((tag "h2")
             (stringToHtml "Welcome to our site!")
         ((tag "p")
            (stringToHtml print_information)
         ((tag "p")
           (stringToHtml print_inline)
         ((tag "div"![strAttr "class" "right column"])
           (stringToHtml render)
         ((tag "div"![strAttr "abba" "ding", strAttr "ding" "abba"])
                                    (stringToHtml "dinger")

le Code

module Main where

import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Language
import Text.ParserCombinators.Parsec.Pos
import qualified Text.ParserCombinators.Parsec.Token as T
import Data.Char
import Data.List
import Data.Maybe
import System.IO.Unsafe

main = do s <- getContents
          case (parse mainParser "stdin" s) of
            Left  err -> putStrLn "Error: " >> print err
            Right hs  -> putStrLn hs

-- Try to parse HAML, otherwise re-output raw lines

mainParser = do whiteSpace
                ls <- many1 (hamlCode <|> tilEOL)
                return $ unlines ls
-- * HAML lexer
hamlLexer = T.makeTokenParser emptyDef
whiteSpace= T.whiteSpace hamlLexer
lexeme    = T.lexeme hamlLexer
symbol    = T.symbol hamlLexer
natural   = T.natural hamlLexer
parens    = T.parens hamlLexer
semi      = T.semi hamlLexer
squares   = T.squares hamlLexer
stringLiteral= T.stringLiteral hamlLexer
identifier= T.identifier hamlLexer
reserved  = T.reserved hamlLexer
reservedOp= T.reservedOp hamlLexer
commaSep1 = T.commaSep1 hamlLexer
-- * Main HAML parsers

-- hamlCode is just many identifiers (e.g. 'func a b c' followed by '=' followed by a hamlBlock
-- func a b c = %somehaml
hamlCode = try ( do is <- many1 identifier
                    symbol "="
                    currentPos <- getPosition
                    x <- manyTill1
                          (lexeme $ hamlBlock)
                          (notSameIndent currentPos)
                    return $ (concat $ intersperse " " is) ++
                             " = \n" ++
                             (concat $ (intersperse (indent currentPos ++ "+++\n")  $ filter (not . null) $ x))

-- A Block may start with some whitespace, then has a valid bit of data
hamlBlock   = do currentPos <- getPosition
                 bs <- manyTill1
                      (pTag <|> pText)
                      (notSameIndent currentPos)
                 return $ intercalate (indent currentPos ++ "+++\n") bs

pTag    = do    currentPos <- getPosition
                    (do t  <- lexeme tagParser
                        ts <- (isInline currentPos >> char '/' >> return []) <|>
                        return $ intercalate "\n" $ filter (not . null) $
                          [ (indent currentPos) ++ "((" ++ (if (null ts) then "i" else "") ++ t  ++ ")"
                          , if null ts then [] else ts
                          , (indent currentPos) ++ ")\n"]

pText = lexeme stringParser

notSameIndent p = (eof >> return []) <|>
                  (do innerPos <- getPosition
                      case (sourceColumn p) == (sourceColumn innerPos) of
                                True  -> pzero
                                False -> return []

-- * Various little parsers

tagParser :: CharParser () String
tagParser = do     t <- optionMaybe tagParser'
                   i <- optionMaybe idParser
                   c <- optionMaybe (many1 classParser)
                   a <- optionMaybe attributesParser
                   if (isJust t || isJust i || isJust c || isJust a)
                       do return $ "tag \"" ++ (fromMaybe "div" t) ++ "\"" ++
                           (if not (isJust i || isJust c || isJust a) then "" else
                              concat $
                               [ "!["
                               , intercalate ", " $ filter (not . null)
                                   [ (maybe "" (\i' -> "strAttr \"id\" \"" ++ i' ++ "\"") i)
                                   , (maybe "" (\c' -> "strAttr \"class\" \"" ++ (intercalate " " c') ++ "\"") c)
                                   , (maybe "" (\kv -> intercalate ", " $ map (\(k,v) -> "strAttr \"" ++ k ++ "\" \"" ++ v ++ "\"") kv) a)
                               , "]"]
                     else pzero

tagParser' :: CharParser () String
tagParser' =  do char '%'
                 many1 termChar

idParser :: CharParser () String
idParser = do char '#'
              many1 termChar

classParser :: CharParser () String
classParser = do char '.'
                 many1 termChar

attributesParser :: CharParser () [(String, String)]
attributesParser = squares (commaSep1 attributeParser)

attributeParser :: CharParser () (String, String)
attributeParser = do k <- identifier
                     symbol "="
                     cs <- many1 identifier
                     return (k, intercalate " " cs)

stringParser :: CharParser () String
stringParser = do   currentPos <- getPosition
                    modifier <- optionMaybe (char '=' <|> char '-')
                    c <- alphaNum
                    cs<- tilEOL
                    case modifier of
                      Just '-' -> return $ (indent currentPos) ++ "-" ++ c:cs
                      Just '=' -> return $ (indent currentPos) ++ "(stringToHtml " ++ c:cs ++ ")"
                      Nothing  -> return $ (indent currentPos) ++ "(stringToHtml \"" ++ c:cs ++ "\")"

-- * Utility functions

isInline     p = do p2 <- getPosition
                    case (sourceLine p  ) == (sourceLine p2) of
                      True -> return []
                      False -> pzero
isSameIndent p1 p2 = (sourceColumn p1) == (sourceColumn p2)

tilEOL = manyTill1 (noneOf "\n") eol
eol = newline <|> (eof >> return '\n')

termChar = satisfy (\c -> (isAlphaNum c) || (c `elem` termPunctuation) )
termPunctuation = "-_"
indent p = take (sourceColumn (p) - 1) (repeat ' ')

manyTill1 p e =  do ms <- manyTill p e
                    case (null ms) of
                      True  -> pzero
                      False -> return ms

Golly, but I wish that I’d cleaned up the code, but there it is in all of its raw, un-thought-through glory…

with 2 comments

ANNOUNCE: Turbinado V0.2 “Still Ugly”

Written by alson

November 26th, 2008 at 2:11 am

Posted in Geekery,Programming,Ruby On rails,Work

Bookmark and Share

More progress on Turbinado. Look! A whole “+0.1”!

Progress continues on Turbinado.  Turbinado can be found at:

The source can be found at:
   (see the /App directory for the code for www.turbinado.org)

New in V0.2:
  * A better "Environment" type (rather than using Dynamics) (-> a 50%
speed boost?  That's unpossible!);
  * A functional early version of an ORM for PostgreSQL (note: still
needs to handle updates; hdbc-postgresql has a bug with sensing
nullable columns);
  * A prettier website;
  * Licensing -> BSD.

Expect V0.3 in the next week or so with:
  * More view helpers;
  * An ORM which handles INSERT/UPDATE...;
  * A little CMS built using the ORM.

Future release:
  * Separate the website out from the framework.  For now, they're
evolving together, so live together. 

without comments

ANNOUNCE: Turbinado V0.1

Written by alson

November 18th, 2008 at 2:10 am

Posted in Geekery,Programming,Ruby On rails

Tagged with

Bookmark and Share

Posted to the Haskell mailing list:

I'd like to announce Turbinado, a very young and raw MVC web framework
for Haskell.  While the framework doesn't exactly copy Ruby on Rails,
it certainly rhymes...  It's very early days for Turbinado, but the
framework is moving along nicely.  There are still issues to be ironed
out and architectural details to be decided, so help/contribution would be
very much appreciated.

Turbinado can be found at:
<a rel="nofollow" href="http://www.turbinado.org/" target="_top">http://www.turbinado.org</a>

The source can be found at:
<a rel="nofollow" href="http://github.com/alsonkemp/turbinado/tree/master" target="_top">http://github.com/alsonkemp/turbinado/tree/master</a>
(see the /App directory for the code for www.turbinado.org)

* Provides a fast web server (based on HSP; see
<a rel="nofollow" href="http://turbinado.org/Home/Performance%29;" target="_top">http://turbinado.org/Home/Performance);</a>
* Provides a straightforward organization for your website (courtesy
of Rails);
* Uses simple HTML-like templating (courtesy of HSX);
* Is easily extensible (courtesy of an Environment built out of _Map
String Dynamic_, not the most type-safe of beasties; Help!);
* Configurable routing (see Config/Routes.hs).

Turbinado is currently lacking:
* Documentation...
* An easy install...
* A database ORM based on HDBC (visibly incomplete and ugly in
* Many more HTML helpers;
* Controllers for partials (lightweight "controls" ala ASP.NET);
* Strong error reporting and handling;
* Lots of functionality and plugins;
* ... the favorite feature that you want to develop for Turbinado ...

without comments

Commentary: “RMS hates cloud computing; says you should too”

Written by alson

October 3rd, 2008 at 10:35 am

Posted in Business

Tagged with ,

Bookmark and Share

See here for a much discussed article on how RMS has said he hates cloud computing.  I’m usually pretty on board with what RMS says (after I filter out the uber-geek-bias), but I’m on the fence about this issue.

My counter argument to RMS’s argument is: Damn!, but online services are just too handy to leave aside in order to maintain software development philosophical purity.  Would you give up online e-mail, social networks, etc?

Besides, I love having fewer applications installed on my computer.  I install and focus on the applications I really, really need and the other needs are served out there in the cloud.

RMS’s comment strikes me as purely academic with little consideration for What Really Works.  I hope that online e-mail doesn’t go away, but I’d love to know how to make it more GNUy.

without comments