Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
Haskell hacking
[go: Go Back, main page]


Haskell Hacking: a journal of Haskell programming



2006-09-10

Syntax highlighting for the planet

planet.haskell.org now supports syntax highlighting of Haskell code using Malcolm Wallace's HsColour tool. To colorise your Haskell fragments, build and install HsColour, and run it with -css. The following source:

-- main :: IO ()
main = print $ case Just e of
        Nothing -> error "no return"
        Just x  -> x
    where e = map (+1) [1..100]
Handed to HsColour, and then prune the head and body tags, leaving a css-ified pre markup:
$ HsColour -css A.hs | sed '1,/body/d;s,</body>,,;$d'

-- main :: IO ()
main = print $ case Just e of
        Nothing -> error "no return"
        Just x  -> x
    where e = map (+1) [1..100]
Which uses the css tags defined here. Happy typesetting!

/home :: /haskell :: permalink :: rss

QuickCheck for the IRC masses

Lambdabot's plugin list keeps growing. We now have a QuickCheck plugin. QuickCheck is a rather spiffy unit test generator/framework, used particuarly for checking invariants in Haskell libraries. The lambdabot plugin makes it available from irc or the command line, to check properties of Haskell code. Ok, something basic:

lambdabot> check True
 OK, passed 100 tests.

A bit more complex:

lambdabot> check False == True
 Falsifiable, after 0 tests:

A list property:

lambdabot> check \s -> (reverse . reverse) s == id (s :: [Int])
 OK, passed 100 tests.

Or for partial functions:

lambdabot> check \s -> (head . sort) s == minimum (s :: [Int])
 Exception: Prelude.head: empty list

Ah, so better specify the precondition:

lambdabot> check \s -> not (null s) ==> (head . sort) s == minimum (s :: [Int])
 OK, passed 100 tests.

Or an invalid property:

lambdabot> check \s -> not (null s) ==> (head . sort) s == maximum (s :: [Int])
 Falsifiable, after 2 tests:
    [1,0]

We can hook this into the free theorem's plugins, just for fun:

lambdabot> free filter
$map f . filter (g . f) = filter g . $map f

lambdabot> check \f g s -> (map (f::Int->Int) . filter (g . f)) s ==
                           (filter g . map f) (s::T)
OK, passed 100 tests.

And we're already using it to answer language questions! Live from #haskell:

16:46  glguy:: ?type rem
16:46  lambdabot:: forall a. (Integral a) => a -> a -> a
16:46  glguy:: ?type mod
16:46  lambdabot:: forall a. (Integral a) => a -> a -> a
16:46  glguy:: synonyms?
16:51  dons:: ?check \a b -> a `rem` b == a `mod` (b :: Int)
16:51  lambdabot::  Exception: divide by zero
16:51  glguy:: heh
16:51  dons:: ?check \a b -> b > 0 ==> a `rem` b == a `mod` (b :: Int)
16:51  lambdabot::  Falsifiable, after 8 tests:
16:51  lambdabot:: -3
16:51  glguy:: ohhh negative numbers
16:51  dolio:: Ah, there you go. Dividing by negatives is different.
16:51  dons:: ?check \a b -> (a > 0 && b > 0) ==> a `rem` b == a `mod` (b :: Int)
16:52  lambdabot::  OK, passed 100 tests.
16:52  dons:: ?check \a b -> (a < 0 && b > 0) ==> a `rem` b == a `mod` (b :: Int)
16:52  lambdabot::  Falsifiable, after 6 tests:
16:52  lambdabot:: -2
16:52  dons:: QuickCheck++

/home :: /haskell :: permalink :: rss

Archives

Recommended

Blog Roll

Syndicate