Hackfoofery

Alson Kemp

Archive for the ‘Haskell’ Category

Cyptol on Slashdot

without comments

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!

Written by alson

December 26th, 2008 at 4:02 pm

Posted in Haskell

Turbinado: Implementing a poor-man’s wiki

with 18 comments

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:

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

CREATE TABLE page (
    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>
          <h1>
            Page Index
          </h1>
          <% do ls <- getViewDataValue_u "pages-list" :: View [(String, String)]
                mapM indexItem ls
          %>
        </div>
 
-- 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>"
                   ,"</div>"
                   ]

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 %>
        </div>

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.

Written by alson

December 20th, 2008 at 8:08 pm

Posted in Haskell,Turbinado

Turbinado update

with 2 comments

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.

Written by alson

December 18th, 2008 at 2:13 pm

GitHub, ‘git’ and the forking fallacy

with 3 comments

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.

Written by alson

December 18th, 2008 at 1:04 am

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

with 15 comments

[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 »

Written by alson

December 16th, 2008 at 1:33 am