Archive for the ‘code’ Category

Parameterised monads

Sunday, February 15th, 2009

This post assumes some knowledge of Haskell, in particular what monads and monad transformers are. It's literate Haskell, which means you can load it into ghci directly (well, you'll probably have to convert HTML entities to plain text first, particularly > and <.)

> {-# LANGUAGE NoImplicitPrelude, MultiParamTypeClasses, FunctionalDependencies #-}
> {-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances #-}
> 
> import Prelude hiding (Monad (..))
> import qualified Prelude as P
> import Control.Monad.Trans

On the Haskell blog circuit recently the notion of "parameterised monad" has been floating about, provoked by a new paper "Parameterized Notions of Computation". I'll refrain from explaining it myself, instead linking to Dan Piponi's post on the topic. If you don't already know what parameterised monads are, go and read that.

It seems that a module has already been written to encode parameterised modules and uploaded to Hackage: Control.Monad.Parameterized (package monad-param). It dates from before the current excitement (2007 and it's at version 0.0.2) so the concept is apparently not new. It does however take a somewhat different approach, one that's seemingly more general but also more cumbersome. The change in approach is explained in a blog post by its author, Edward Kmett. Here's what the "parameterized monad" class would look like if translated from the paper:

(more...)

Static typing and correctness

Wednesday, March 19th, 2008

I've been pointed to a post by Joel Spolsky advocating Hungarian notation so that code that fails to properly sanitise strings "looks wrong".

Here's Joel's example. The idea is that you prefix the names of all string variables and functions returning strings with either "s" or "us" depending on whether they're safe or unsafe respectively. Then assignments that have "s" on one side and "us" on the other just look wrong.

us = UsRequest("name") // ok, both sides start with US
s = UsRequest("name") // bug
usName = us // ok
sName = us // certainly wrong.
sName = SEncode(us) // certainly correct.

Well I can think of one pitfall already. How do you mark whether a function expects safe or unsafe data in a way that makes wrong code look wrong?

us = UsRequest("name") // okay
RandomMangler(s) // okay
RandomMangler(us) // errm... wrong?

If you're using a language that supports it, there is a far better way. (more...)

How to cheat at Mensa puzzles

Saturday, February 9th, 2008

At freshers’ fayre (yeah, a long time ago now) I was handed a slip from Mensa. I intended to follow it up later but being busy I never got round to it. Today I rediscovered it on my desk, and of course it had a couple of puzzles on it. One is a pretty simple number sequence. The other has you find an anagram:

Rearrange the letters of ‘ANY TIME‘ to give a seven letter word. What is it?

Obviously “anytime” is excluded (well, we’re not Americans ;). I tried to find one manually for a while, but then realised I could just solve it with a couple of commands:

[pwb@rhuidean ~]$ ghci -e 'Monad.mapM_ putStrLn (let s = "anytime" in filter (\s2 -> all (`elem` s2) s) $ Control.Monad.replicateM 7 s)' > words
[pwb@rhuidean ~]$ grep -f words /usr/share/dict/words

This was taking a long time. But then I realised you can cut out a big chunk of the search space by filtering out all the non-anagrams, which you can do easily with grep.

[pwb@rhuidean ~]$ grep '^[anytime]{7}$' /usr/share/dict/words | grep -f words
amenity
anytime

I wonder how this reflects on my intelligence… :)

More from the list monad

Wednesday, July 18th, 2007
Prelude Control.Monad> let truthPermutations n = replicateM n [False,True]
Prelude Control.Monad> truthPermutations 3
[[False,False,False],[False,False,True],[False,True,False],[False,True,True],
[True,False,False],[True,False,True],[True,True,False],[True,True,True]]
Prelude Control.Monad> let satisfies p [x,y,z] = p x y == z
Prelude Control.Monad> filter (satisfies (==>)) $ truthPermutations 3
[[False,False,True],[False,True,True],[True,False,False],[True,True,True]]

Try expressing truth tables so succinctly and at such a high level in an imperative language. The list monad rocks.

One-line definition of the power set function

Monday, July 2nd, 2007

If you thought the one-line definition of the Fibonacci sequence in Haskell was beautiful, try this:


import Control.Monad
powerset :: [a] -> [[a]]
powerset = filterM (const [True, False])

A black box for sure, unless you have “internalized the list monad“. But it does show how stonkingly powerful monads are.

Unix pipelines vs. lazy evaluation

Sunday, June 3rd, 2007

(In response to Gimbo.)

Speaking of Unix, I have thought that there is a pretty close connection between lazy evaluation and Unix pipelines. On the xmonad home page there’s an example for using dzen that looks like this:


while true ; do
    date +"%H.%M %a %b %d"
    sleep 60
done | dzen2 -ta r -fg ’#a8a3f7’ -bg ’#3f3c6d’


Of course, if that was strictly/eagerly evaluated, dzen would never run, because of the infinite loop. But what actually happens is that the two commands, joined together by a pipe (indicated by the | character), are executed in parallel; the while loop runs date, producing some output, which it writes to a pipe (just a first-in-first-out buffer shared by the two processes); it sleeps for 60 seconds; then it runs date again; sleeps again; …, ad infinitum. Meanwhile, dzen reads its output, until there is none left, then blocks until the loop provides more.

(more…)

Type inference rocks

Monday, May 28th, 2007

I just wrote the following snippet of code for my dissertation:


intNatI :: Int :~= Nat
intNatI = Iso {
            to   = fromInteger . toInteger,
            from = fromInteger . toInteger }

The components to and from have totally different types (to is Int -> Nat, from is Nat -> Int). Yay for type inference! :)

QOTD VIII

Wednesday, February 7th, 2007


Quoth Doaitse Swierstra, nevermore,
>  digest.chew.eat.serve.cook.chop.pluck.kill $ chicken
>
> we all have a definite feeling that after applying the functions, the
> original object is no longer available, and the FP view does not feel
> entirely natural.

Yes, that is true. I can sort of see why people might object to the IO
monad in this case, since it explicitly prevents the programmer from
reusing old data. Of course, one might argue that it's not really the
*monad* that prevents it, but the construction of the physical world.
The monad merely prevents us from trying to eat our cake and have it.


Dougal Stanton on haskell-cafe (archive).


For the uninitiated, the dots refer to function composition; in OO notation it would look like chicken.kill().pluck().chop().cook().serve().eat().chew().digest(). The point is that that kind of composition in Haskell implies there are no side effects. Consider:


let chicken = getChicken
in  (chicken,
    (digest.chew.eat.serve.cook.chop.pluck.kill) chicken)

Here we’ve taken a chicken, eaten it, and returned the result along with the original chicken — i.e, we eat our chicken and have it. This is what the IO monad stops you from doing, and why composing functions that perform side effects is difficult.


This is perhaps a good introduction to a rather interesting video I also saw linked from haskell-cafe (in fact in the same thread). It’s only available in WMV unfortunately (it does come from MS after all).

Milliways and the equivalence of programming languages

Friday, January 26th, 2007

It’s been known since the time of Turing that what’s computable in one reasonably powerful programming language is computable in every other one. As a result, we can say that large classes of programming languages are ‘equivalent’ in the sense that they can emulate each other. However, not all programming languages have natural equivalents of all the others’ features.

This is the idea behind Greenspun’s Tenth Rule:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

The usual corollary is “including Common Lisp”. We could say the same for C: most C compilers are implemented in C and compile themselves. Similarly, the Glasgow Haskell Compiler is written (mostly) in Haskell. Actually, given that C is the implementation language for so many interpreters, it’s easy to see that one could, in principle, write a program in language X by directly creating the abstract syntax tree and passing it to an “evaluate” function, all in C.


(more…)

Monadic fractals

Sunday, December 17th, 2006

There are an awful lot of monad tutorials out there. Monads as containers is one I saw a link to on haskell-cafe today, and it gives a rather amazing application of the list monad:


f x | x == '#'  = "# #"
    | otherwise = "   "
"#" >>= f >>= f >>= f >>= f
= "# #   # #         # #   # #                           # #   # #         # #   # #"

And we have a fractal!