Friday, March 6, 2009

F#: Haskellers beware!

Equational reasoning may fail you. F# land is the land where nuclear missiles are launched all the time, and puny gnomes carry wands of death.
#light

let g = new System.Random()
let s = Seq.init_infinite (fun _ -> g.NextDouble())

/// You thought 'a seq is Haskell [a]? Not quite! It does not memoize:
printfn "%A" (Seq.hd s, Seq.hd s) (* Surprise! fst and snd differ! *)


type X = 
    static member X = g.NextDouble()

/// You thought X is a value? Not quite! It is a property (think function):
printfn "%A" (X.X, X.X) (* Surprise! fst and snd differ! *)

Thursday, March 5, 2009

F# interface implementation - is `unit` special?

#light

type 'a A = 
  interface
    abstract member A : unit -> 'a
  end

let x = { new int  A with member x.A() = 1 }  // ALLOWED
let y = { new unit A with member x.A() = () } // ERROR?

Cyrillic typesetting in LaTeX on Arch

Write foo.tex:
\documentclass{article}
\usepackage[T2A]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage[russian]{babel}
\usepackage{ucs}

\begin{document}
Привет, мир!
\end{document}

Then pdflatex foo.tex.

Arch package required: texlive-langcyrillic.

Wednesday, March 4, 2009

F# Quirks

A feature or a bug?

An innocent-looking pair of parentheses ends up influencing the runtime representation of discriminated union types.

I would prefer not to have this. The two representations seem conceptually redundant, it would be better to just pick the faster one.

Given this foo.fs:

#light

open Microsoft.FSharp.Reflection

type A1 = A1 | B1 of (A1 * A1)

type A2 = A2 | B2 of A2 * A2


printfn "%A" ((FSharpType.GetUnionCases(typeof<A1>)
              |> Array.map (fun x -> x.GetFields())));;

printfn "%A" ((FSharpType.GetUnionCases(typeof<A2>)
              |> Array.map (fun x -> x.GetFields())));;

Run fsi --quiet --exec foo.fs to produce this:

[|[||]; [|Microsoft.FSharp.Core.Tuple`2[FSI_0001.Foo+A1,FSI_0001.Foo+A1] B11|]|]
[|[||]; [|FSI_0001.Foo+A2 B21; FSI_0001.Foo+A2 B22|]|]

I found this code while testing a library that produced different results depending on the presence or absence of the parentheses.

Update: A feature! Thanks to Zedd. I should know my specs and my OCaml:

Objective Caml version 3.10.2
# type c = C of int * int;;
type c = C of int * int
# match C(1, 2) with | C x -> x;;
The constructor C expects 2 argument(s), but is here applied to 1 argument(s)
# type c = C of (int * int);;
type c = C of (int * int)
# match C(1, 2) with | C x -> x;;
- : int * int = (1, 2)
#

Saturday, February 28, 2009

Ubigraph - I wish!

I wish we had this this when I was modelling social networks for my thesis!!

Friday, February 27, 2009

hdaemonize on hackage

Having got a green light from Andre, I uploaded hdaemonize to Hackage.

I also cleaned up the library a bit. Reading up on POSIX signals I decided that it is wrong for the daemonize library to mess with them beyond blocking HUP. Also, now it has two functions, daemonize :: IO () -> IO () which does the bare minimum, and serviced :: Program -> IO () that does that and more, for example writing a PID file, handling start/stop/restart, catching and logging exceptions to syslog.

Time to try it out in production.

R Language - once more

An early warning for the unwary hacker.

Normal-order evaluation

Y <- function (f)
  (function (x) f(x(x))) (function (x) f(x(x)))

FAC <- function (f) function(n)
  (if (n == 0) 1 else n * f(n - 1))

> Y(fac)(10)
[1] 3628000

Quoting and macros

fn <- function(x) {
   x <- substitute(x);
   f <- list(NULL, x[[2]]);
   names(f) <- c(x[[3]], "");
   as.function(f, envir=parent.frame());
}

y   <- fn(f -> fn(x -> f(x(x)))(fn(x -> f(x(x)))))
fac <- fn(f -> fn(n -> if (n == 0) 1 else n * f(n - 1)))
> y(fac)(10)
[1] 3628800

Coercions

> NULL == FALSE
logical(0)

If you are wondering what happened here, FALSE, which is a logical vector of length 1, was compared for equality with NULL, which is an empty list. To proceed with the comparison, R coerced the list to a vector of length 0. Then, two logical vectors were compared elementwise for equality, to yield the resulting vector of length 0.

Equational reasoning is not a good starting point to make sense of this:

> NULL == NULL
logical(0)

> logical(0) == FALSE
logical(0)

Side effects

> f <- function () { print("MISSILES LAUNCHED"); 1 }
> g <- function (x <- f()) { x + 1 }
> g()
[1] "MISSILES LAUNCHED"
[1] 2
> g(1)
[1] 2

Argument parsing

> f <- function (x = y + 1, y = x + 1) { y <- 2; y }
> f()
[1] 2

Summary

Can a language safely combine the above features?

Does statistics really nead such a language?

References