Wikileaks: Where the Hole is Big Enough to Drive a Truck Through

When I first heard about Wikileaks, I felt that possibly they were providing a much needed ‘heads up’ to the public on important International concerns such as the wars in Iraq and Afghanistan.   When I heard about the recent cable releases, I thought they caught the United States in some particularly heinous territory with their International Policy — something that represented a serious shift from the norms of behavior that the country’s citizens would expect from the people who represent them abroad.

Instead, it’s just a leak of cables.   Stories of Omar Khadaffi oogling voluptuous Ukranian blonds.   CSIS members complaining about lawyers.   Frank opinions about Russian dignitaries.    All great stuff to sell newspapers and boost the ego of the ‘leakers’ but nothing representing an international emergency.    Given this lack of urgency, it is my opinion that Wikileaks did the wrong thing when they leaked this information.     There is no ethical standard that I can apply that justifies their actions here.    Let’s go over some of the tests.

Let’s start with Emmanuel Kant’s ‘categorial imperative,’ act only according to that maxim whereby you can at the same time will that it should become a universal law.   I do not accept left-wing minds ought to be allowed to leak private documents to undermine aggressive international policy because I know that right-wing minds would more than enjoy the opportunity to leak medical documents and doctor reports to undermine expensive public health care.

Now, I do not accept Kant wholeheartedly.   I do believe we should make room for exceptions in cases where the action provides a benefit, or prevents a negative that greatly outweighs the negatives that come from the action.     A deontological (Kantian) mind must have a utilitarian conscience.   So, taking the Trolley problem example, I do think there is some justification for pulling the switch that kills one person when it means saving the lives of thousands.    With some clear (and very important) caveats:

  • there is clear evidence of public benefit
  • there is no apparent self-interest in pulling the switch
  • the one person is not known to be vulnerable within the society (see Rawls)

Clearly, I do not see a clear public benefit to the leaks.    I do, however, see plenty of self-interest as media outlet after media outlet uses the juiciest elements of the cables to sell their papers.    The damage that this leak causes, however, will never be quantified.    Government Services will be regulated and secured to the point that they are no longer services in any sense of the word.   Foreign Affairs agents will always be thinking about their (needed) frank opinions in the context of these leaks.   In the best case scenario, this means embarrassment for public officials.   In the worst case scenario, this means a disconnect between diplomacy and policy – which is a euphemistic way of saying “stupid Wars caused by miscommunication.”

The final test is one of my favorites, put out by John Rawls — the ‘original position’ test.   This test would offer that people should act as if they came into society with no understanding of its norms or structure.    The person in this position would want the society that protected its most vulnerable members (because, given no prior understanding of status, someone would want to ensure that they had a decent lifestyle no matter their status).      The so-called transparent society that so many internet lovers desire is not to the advantage of the most disadvantaged.    For one, the most disadvantaged likely have no clue whatsoever that this whole Wikileaks thing ever happened.    All they’ll know is that some authority figure in their country will put two and two together (correctly or incorrectly) and accuse them (correctly or incorrectly) of treason based on pieces of evidence found in these documents.

In short, there is no real ethical justification in my mind for leaking these documents to the public, only a half-baked and obnoxious internet ideology.    It was a wrong-minded action and it should be punished in my view.   Fortunately for the people involved — people who are by no means the vulnerable people John Rawls wanted us to consider — they will be punished in a country that believes in ethical treatment of their citizens and fair trials.

For shame.

Haskell Tutorial IV : If This is A Case of Functional Programming, Then I am Switching to Lazy Evaluation

Part III: How Haskell Monads are Like a Muppet       Part: V   (coming soon) >

Finally, with the forth part of the tutorial, I get to describe something that will make my PHP-coding reader want to use Haskell:  lazy evaluation.

But first, let’s go back to two different ways I’ve approached the problem of evaluating a keyboard input from a user in our rogue-like RPG game.    In tutorial #2, I created a function called move that used guards to discern what action to take based on a given input.    Here is move:

move :: Char -> String
move a
    |  a == 'w'       = "UP!"
    |  a == 's'       = "DOWN!"
    |  a == 'a'       = "LEFT!"
    |  a == 'd'       = "RIGHT!"
    |  otherwise      = "HANG AROUND AND DO NOTHING!"

In tutorial #3 I switched to a series of if / else if / else statements.

forever (do
    char <- getChar
    if char == 'q' then putStrLn "Thanks for Playing!"
         else if char == 'w' then up y >> output x >> output y
         else if char == 's' then down y >> output x >> output y
         else if char == 'a' then down x >> output x >> output y
         else if char == 'd' then up x >> output x >> output y
         else putStrLn "you did not type a correct entry")

This version had the additional side effect of requiring a manual escape of the compiler program in order to quit (something that is easily fixable, but still).    Now I have a new function ‘dashboard’ that uses lazy evaluation to compute values based on a given input.   Without beating around the bush, here it is:

dashboard :: Char -> MVar Int -> MVar Int -> IO ()
dashboard 'q' _ _ = exit "Thanks for Playing!"    // stop the program
dashboard 'w' x y = up y >> putStr " Coordinate: ( x = " >> output x >> putStr " , y = " >> output y >> putStr ")."
dashboard 's' x y = down y >> putStr " Coordinate: ( x = " >> output x >> putStr ", y = " >> output y >> putStr ")."
dashboard 'a' x y = down x >> putStr " Coordinate: ( x = " >> output x >> putStr ", y = " >> output y >> putStr ")."
dashboard 'd' x y = up x >> putStr " Coordinate:  ( x = " >> output x >> putStr ", y = " >> output y >> putStr ")."
dashboard w x y = putStr " Coordinate: ( x = " >> output x >> putStr ", y = " >> output y >> putStr ")."   // keep the Coordinate values the same

So, let’s think about our problem for a second.    So far, we have been focussed on getting our character to move around a map.    But what if we want to do something completely different, like say show an inventory list if the user hits ‘i’?    Or maybe cast a spell?     We could have a bunch of if – then statements or a whole bunch of guards, but it all could end up being a mess and impossible to read.

Fortunately, Haskell let’s you specify particular actions based on the constructors (entry values) for your function.    In the case above, dashboard accepts 3 values — one CHAR and two MVar Ints (ie. a mutable variable that has to be an integer — see the previous tutorial).   If the dashboard receives a ‘q’ for a value, it will say ‘thanks for playing’ and quit the program (the two ‘_’s mean it doesn’t matter what the values are that follow it).   The next entries do what we’ve come to expect -> change the value of the MVar based on the movement and then output the current coordinate’s status.    The last statement is a catch-all, asking Haskell to output the current spot.

Why might this way of doing things be better than using (say) guards?    Well, the first reason is that it gets to the point.    if the user hits ‘q’, Haskell will not attempt to evaluate any of the other function calls.   Admittedly, this function isn’t really helped performance-wise by lazy evaluation -> but what if moving in a certain direction (in the spot where a monster was) involved a long series of recursive computations.    We would not want Haskell to be using up its resources trying to figure out what it’s supposed to do when all the user wants to do is quit.

However, there’s still alot that could be added here.   What if we want to do something when the user hits ‘s’ and y is equal to zero.    Then we could do something like this:

dashboard 's' 0 y putStrLn "You are blocked and can go no further."  >> putStr " Coordinate:  ( x = " >> output x >> putStr ", y = " >> output y >> putStr ")."

Again, this can have really great performance benefits for your program.    If dashboard gets an ‘s’ and a ‘0’, it will look no further and do the easy job of outputting the coordinate as is, rather than attempting to go through all kinds of irrelevant processes.   UPDATE:  Well, actually, this is all wrong.    Because ‘0’ is not an MVAR.    Mind you, there is a way to get the function to accept two Ints instead and convert the MVAR to an Int for our purposes.    That’ll be another tutorial though.

The last benefit is that it gives a nice human-readable understanding of what happens when the function receives what, without a whole range of complex nested elements.

The downside, of course, is that because Haskell is type-safe, you must give this function a CHAR (not a Maybe Char, or a String) and two MVAR Ints (not an MVAR String or ordinary Int) or you will get a type error.       Things could also get more confusing if you decide that you want to return an IO (String) or other value instead of just outputting something to the screen.    But handling that problem might be for another tutorial.

I should, again, remind you that my up-to-date work on the rogue-like game called rasghiosse is available in a patch-tag repository.   Please feel free to add to it as you wish.

Part III: How Haskell Monads are Like a Muppet

< Part II: How not to Start Your Haskell Program Part: IV:  If This is a Case of Functional Programming, Then I Am Switching to Lazy Evaluation >

In previous tutorials, I talked about some assumptions about Haskell programming, and how to overcome them.    I suggested that someone coming from an imperative background (more than likely) is going to go about functional programming all wrong.     I fretted that no one creating documentation for Haskell seemed to notice this and that this was a problem for the future of Haskell and functional programming in general.

Non-academic coders want to make their programs *do* something as soon as they can.      Academic programmers are more fascinated by making their code solve complex problems.     Making Haskell do something is possible, but you’d never know it by reading through the documentation and most tutorials.    Here I will make our Haskell program actually do something, all the while giving an inkling about how state monads / MVars / IORefs work (without ever bothering to explain the math-ese behind them).    Again, I am assuming you’ve read and have been confused by at least one or two tutorials on the subject.

Because imperative programs rely on mutable variables (of which functional programming has none), programmers usually start by creating controls mechanisms (eg. an array in php) to prevent mean side effects from creeping in to their software.    Functional programming does not have side effects.    That’s good.   However, it also does not have the ability to store values inside a variable.    That’s bad.   That’s why I suggested starting with input and output and filling in the gaps.   Then I gave a sample:


main :: IO() main = do
                        x <- getChar
                        if x == 'q'  then putStrLn "Thanks for Playing"
                            else pmove x >> main  

move :: Char -> String
move a
    |  a == 'w'       = "UP!"
    |  a == 's'       = "DOWN!"
    |  a == 'a'       = "LEFT!"
    |  a == 'd'       = "RIGHT!"
    |  otherwise      = "HANG AROUND AND DO NOTHING!"  

pmove = print . move

So far, this program doesn’t do much more than a basic “Hello World!” program.     It accepts an input that get stored in x and based on that input it prints out a word.   Pretty disappointing.   What we want is the ability to change things.    What would be really nice is graph coordinates indicating a plot on a map, for instance.    Then we could establish our character’s position that could be displayed graphically and used to analyze the characters position against (say) a wall, or a monster.   Then the real fighting can begin.

Except you can’t really do that.    If you create a variable ‘place’ that contains a tuple (5, 5), it will always be (5, 5).   Your character is stuck in the quicksand!

You *can* create a function ‘up’ that will increase the ‘y’ value when your user presses ‘w’.    Maybe it’s something like this:

up :: (Int, Int) -> (Int, Int)

up x = (fst x, (snd x) + 1)

However, you are still stuck because you have no declaration of a starting point unless you declare a variable.    If you declare a variable, then your starting point is unchangeable, so you can only move one spot and no more!      This is where you start questioning if Haskell is just some practical joke that some prof wanted to play on his or her students.   In academic terms, this is the ‘problem of state’ and is one of the main reasons why functional programming has not had much influence in its first 30 years of being in existence.

To avoid a surprise ending, the solution is actually to create an MVar, which means ‘mutable variable’ and can be found in the Control.Concurrent.MVar module.    But I am getting ahead of myself.   An MVar isn’t exactly a mutable variable, although it does a really good job at pretending it is one.   Let me use some of my mad working-with-kids librarian skillz to show you how it works.

Grover is a Monad

Since you are somewhat familiar with the Haskell tutorials, you know what a monad is.    You are also a little bit confused at how it works.   I am not going to explain it.   It’s too mathy.    Much better to talk in Muppets.     I like to read a book called Grover’s own alphabet to my kids.     In it, Grover moves his arms and legs around to shape himself into all of the letters of the alphabet.     Believe it or not, this is your solution to the mutable variable problem.

As discussed, I cannot create a function that will store a value in a variable that can be changed later.    However, I can ask a function to return a type.    I can call this type “Grover.”     So, if I’m looking for a letter of the alphabet, I can ask Grover to move his arms and legs so that he is in the shape of a letter, let’s say “G.”    He will stay in “G” until I ask what shape he’s in.     Once he says “I am in shape G”, then he will stand up straight (no shape) until I ask him to take another shape.   This is basically how Monads (more specifically, state monads) work.

(Incidentally, the idea of using Monsters as an example of the Monad type is not new.)

Now is the hard part – going through the documentation.     I am going to save you alot of time.   For our Rogue-like game, we need MVars.    Before figuring this out, I had to go through a whole lot of confusing reading and mess.     If you want some pain and suffering, look up the State Monad, State Transformers, IORef, Arrow notation and the like.    Now look at what you really need.   MVars.    Go ahead and read the documentation on that.   You’ll find out that MVars are used for supporting concurrent processes.    Then you’ll go back to IORefs because this isn’t a concurrent program.    That’s a pointless exercise – IORefs are unnecessary.    And, hey – maybe our Rogue-like game will need to be an MMORPG down the line, who knows?

Here is the code.      I will go through it in more detail in the next tutorial later, but basically this program will start with x = 0 & y = 0, and output a location or a message depending on what you hit on the keyboard.     Note, however, at this stage that you’ll need to hit ctrl-z to make the program stop.



import Control.Concurrent.MVar
import Control.Monad

main = do
           x <- newEmptyMVar
           y <- newEmptyMVar
           putMVar y 0
           putMVar x 0
           forever (do
                    char <- getChar
                    if char == 'q' then putStrLn "Thanks for Playing!"
                        else if char == 'w' then up y >> output x >> output y
                        else if char == 's' then down y >> output x >> output y
                        else if char == 'a' then down x >> output x >> output y
                        else if char == 'd' then up x >> output x >> output y
                        else putStrLn "you did not type a correct entry")

up, down, output :: MVar Int -> IO()
up y =  do
             v <- takeMVar y
             putMVar y (v + 1)

down y = do
             v <- takeMVar y
             putMVar y (v - 1)

output y = do
             g <- takeMVar y
             putMVar y g
             putStrLn (show g)


It’s not the prettiest code in the world, but that’s how you have to do it with Haskell.   Start out ugly, and make it pretty as you go along.

Ryan’s Rules for Website Navigation

It should be intuitive.’   ‘The user should not have to hunt for information.’ Focus on the user.’

Yes.   So, ‘yes’.    If everyone can agree on these things, why don’t we see it in practice?    As usual, the Devil is in the details.    Making a website (or any other kind of software) usable is harder than it seems.     While you’d think great designer can handle all usability problems, it takes more than just usability ‘chops’ to create a great website.    Even with testing, there are a variety of factors that can influence a website’s design – even when everyone has the user at heart.    So, here are a few tips I have to help a little.    For the sake, of brevity I am going to focus in on navigation.

Fewer Labels is Always Better

It works like this:   if you see a relevant path on a website, you will click on it.    If you do not, you will take your next best guess.    Every label does not have to be as explicit as you think it does.   Remember always the Pareto Principle / The 80-20 rule.    Of all the content that gets submitted to a library website, only 20% is vital to the user.    That 20% needs clear, concise & obvious navigation.

Do not let the other 80% get in the way of the vital 20%.    If someone has to make a guess, a navigation system of 4-5 elements is much, much better than a navigation of 25+ items (number taken from a website I am currently responsible for – ‘do as I say …’ ).   You can cheat a little by having different levels of navigation (eg. About, Contact, Jobs etc. in small at the top or bottom), but most website navigations I see out there go way beyond cheat.

Text, Text, Text

Over and over again, people think that promotion via images is important.    It is, if your user base is 10 years of age or younger.   Images get ignored by the user, and often by search engines as well.   A single word or two, explaining where the link will take you is fine.

In fact, I once took an image link off the front page of a website, gave it a logical name and put it in a less obvious place and the use *increased*.

End the Drop-Down Madness!

WordPress.com, I’m talking to you!     Updating my blog has become hell ever since you changed the navigation to include drop-downs.    I click on the wrong things all the time, then I struggle to get back where I was.    Fortunately, this is only for the back-end interface.    For a front-page interface, drop-downs are even more hellish.

Drop downs came into existence because someone came up with the stupid ‘3 clicks or I’m gone’ axiom.     Everyone came to the conclusion that we needed to design sites to reduce clicks, and drop-downs reduced clicks.    However, the real problem was usability.    Drop-downs reduced clicks, but did not increase usability.    It was a zero-value trade-off.    Don’t use them.

Do Not Believe Everything You Read On the Internet

There’s alot of baloney on the internet, believe it or not.    Some people will tell you that your navigation should use verbs; others nouns.   Some people will decry scrolling; others will insist that the blog is the way to go.   Following anyone’s tips is fine, but they should not be used at the expense of common sense.    For instance, avoiding scrolling for the user may be impossible if you consider that some of your users may still be using 800 by 600 screen resolution or less.

A Link Should Send You to the Place You Expect It

If I click on a link that says ‘find a book’ it should help me find a book.    It should not be a list of tutorials on how to find books.    Call it ‘tutorials’ instead (and then do some serious thinking about whether this is a 20% or an 80% thing).

Don’t Be Cute

If you want to provide a way for people to contact you, call it “Contact” or “Contact Us” not, “Get the Skinny” or something else more barbarous.

The Designer Must Decide

In a profession of information experts, everyone thinks they know how best to design a website.    The problem is that each department sees a different user, and wants to make that user happy.    Reference desk people see the person struggling to access a database.    Cataloguers see the user that can get into the system and download every book they need like it was no tomorrow.   Community workers see people struggling to learn a new language or afraid to walk into the library in the first place.    All are important users.   All have unique needs.

Unfortunately, while we want to make these users happy, trying to make everyone happy at the same time results in a website that puts everything but the kitchen sink on the front page — confusing everyone and pleasing no one.    Alternately, we focus on the users who have a negative experience in brief moment in time – so many factors can play into that complaint (the user’s mood at the time, his or her expectations about library service vs what libraries actually offer etc.).     Of course, we need to take user complaints seriously – but is web design really about solving everyone’s unique problem?   I argue no.    Web design is finding out about how human beings interact with computers / digital media and applying that knowledge to improve access.    A good website cannot solve anyone’s particular information need.    It can, however, make the act of discovery more enjoyable.

All this leads to my conclusion – let the designer decide.    He or she may make a mistake about a particular user’s need (and this will be evident through user testing etc.) but he or she will do a better job of improving access than a committee of people all trying to please their particular vision of the user.

Final Words

If you have been paying attention through the tips, you might have noticed a common thread – the problems website designs encounter are often not design problems at all – they are management, consensus-building and coordination problems.    There is always a delicate balance between alienating your stakeholders and having a process be so participatory that it kills the design.   I would argue that more good designs are killed than bad designs improved.     The killing happens over time as priorities change and band-aids are applied to address minor non-essential issues coming from a variety of different places.

What tips do you have to improve navigation of websites?

Part II: How not to Start Your Haskell Program

< Part I: Is There a Such a Thing as ‘Real World’ Haskell? Part: III   How Haskell Monads are Like a Muppet >

My last Haskell post had me thinking that I might as well create a really bad tutorial outlining my own strategies to deal with Haskell in the real world.    Some of the issues I outlined were:

  • Tutorials for Haskell focussed on solving problems, rather than getting it to ‘do stuff’ which is what alot of users expect from their computer software.
  • Haskell is emerging as an important player in the future of code.   Both as a type of code itself and as a way of improving skills in such languages as Java and Python.   However, it will not make the mainstream unless ‘regular folk’ start using it.
  • Functional programs (in theory) are apt to be more sustainable, less buggy and more consistently documented.   Regular folk, working with imperative and/or objective and pseudo objective languages probably don’t realize this -> not until their code breaks and they have to re-install the wheel.

While I have some experience in other languages like Ruby, and Python, I’ve decided to approach Haskell as if I were a PHP developer instead.     There are some very good reasons for this:

  • PHP is a ‘do something’ language.    Basically, it takes dynamic data and outputs it to a web page.   While math problems and recursion-like methods are possible – it’s usually input and output (ie. taking data in and out of a MySQL database) that is the most important.    Anyone expecting to use Haskell for primarily I/O related stuff is going to die from frustration.
  • PHP code can get very messy, even in the hands of an experienced coder.   Documentation of code is all dependent on comments and external manuals.     Haskell can help your average PHP coder, because its type-system offers a kind of in-source documentation.
  • PHP is a ‘regular peoples’ code.    It is adopted by alot of people with varying skills and experience with computer software, many of whom have very little understanding of its long run limitations.
  • Well into its 5th release, alot of the work has already been done for your average PHP coder.       It’s almost not even necessary to create your own objects and functions with all the pre-created libraries available.     Unfortunately, it’s also widely assumed that you are going to create a web application ->  what if you want to turn your code into an App?    or a desktop application that uses data from a php created api?   or an intense web universe ala Second Life or World of WarCraft?
  • As an interpreted program,   it’s pretty simple to solve problems through trial and error.    Just keep hacking away at php, and eventually you can make some convoluted function do what you want it to do (in an unscalable way, of course).

I am also going to make a number of assumptions:

  1. That you have read through at least some of the Haskell Wikibook.    I do not intend to explain what a Monad is, or impress everyone with my knowledge of complex mathematical theory.    This tutorial is an inquiry about how to approach a Haskell applications, not learning Haskell itself.
  2. You have a fair knowledge of some imperative-style computer language (possibly PHP).

As suggested, I am going to look at developing a one-level ‘rogue-like’ RPG game.      If I were to start such a game in php, I might start with something like:

$playerChar = array ("name" => 'Bob', "class" => 'fighter', "STR" => '18', "DEX" => '14', "WIS" => '11', "INT" => '15');

I suggest this because PHP coders want to get to the action as fast as possible.   The PHP coder (let’s call her PHiP) will know that her first problem is making data output in some consistent manner, so will create a variable that mimics a possible set of data that will eventually be displayed to the screen (likely a webpage).   Knowing that things like the name and class of the character will change, PHiP will put some variables inside the array.    Then PHiP will include some other ideas about what a character will need, and a print_r statement to watch the action as she lashes out blindly for the right outputs:

$playerChar ['traits'] = ("name" => $name, "class" => $class ...); $playerChar ['equip'] = ("weapon" => $weapon, "armour" => $armour ...); print_r ($playerChar);

If you are a Haskell coder, you probably already see countless disasters in store for PHiP if she uses this approach with Haskell.    Here are a few:

  • variables in Haskell are always constant.     Once called, the values will not change.   Believe it or not, functional programmers will see this as a good thing (see side effects in Wikipedia).
  • playerChar [‘traits’] would be seen as a function with an input [‘traits’] that, using Haskell syntax, is a list containing one string value ‘traits’.   Haskell would be wondering what to do if it encountered other lists containing one or more other string value(s).
  • All of the variables inside the associative array $playerChar  are irrelevant in Haskell.  Unless they are constant.
  • Deciding what to do with the array would be overwhelming.    A list could be used, but would require that all values inside be strings.   Or it could be a huge tuple of various kinds of values, or a list of tuples.
  • Without being sure what types of values are needed to create the playerChar, there are almost sure to be problems letting PHiP’s player character switch its weapon from a sword to a mace and back.

In short, PHiP is using the wrong paradigm to code effectively in Haskell.    The issue is not a problem of syntax, or even understanding a problem.   The issue is the approach.

As the tutorial goes along, we will deal with PHiP’s player character.    But, to work in Haskell, I propose that you do not start with the data you want to put in and out.    Instead, you start with input and output itself – inside main – like this:

main :: IO() main = do x <- getChar if x == 'q' then putStrLn "Thanks for Playing" else pmove x >> main move :: Char -> String move a |  a == 'w'       = "UP!" |  a == 's'       = "DOWN!" |  a == 'a'       = "LEFT!" |  a == 'd'       = "RIGHT!" |  otherwise      = "HANG AROUND AND DO NOTHING!" pmove = print . move

Right now, this code is pretty useless, but it offers a few nice things to help make sure you don’t lose steam in your coding.

  • It creates an output that will work (sort of) like PHiP’s print_r string.
  • It offers a practical demonstration of point notation, which, in laymen’s terms creates a function pmove that prints (using print) the results of move.    Essentially, it keeps me from having to write “print (move x)” all the time.
  • I accepts an input ‘a’ that is a character.
  • It creates a strongly typed function ‘move’ that takes a Character and returns a String.   As we move forward, we can chain a series of functions together that will help PHiPs make her Haskell program to do more interesting things such as fight a monster.

(as it turns out, this code works slightly differently in Windows than it does in Linux.    Use the Linux version, because it makes me seem a little more competent.   If anyone can explain why Windows wants the CR for the getChar command, please  add it to the comments.)

I am not absolutely sure this is the very best approach to a rogue-like game, but I can guarantee it is better to start this way than it is to begin with creating variables.     As you read this tutorial, I hope you continue to use other documentations elsewhere to help you get your mind around my use of ‘do’, ‘getChar’, ‘putStrLn’ and guards ‘|’ here (pretty rudimentary Haskell code right now).

The next tutorial will look at shaping our dungeon and establishing where our player as he or she moves across the board.

Incidentally, as of writing this, I am working on a rogue-like game with my son called Rasghiosse (my son named it).    I have a public Darcs repository on Patch-Tag that you are free to join in on if you like.   As of writing this tutorial, I am not much further ahead than the above code, so I would appreciate your help.