Greg Buchholz's blog

Logical variables in Prolog

Submitted by Greg Buchholz
on June 22, 2009 - 11:55pm

I came across this code, which was supposed to demonstrate a Prolog program that couldn't be written in Mercury. I couldn't help but rewrite that as:

rank(Xs,Rs) :- pairs_keys_values(Decorated,Xs,Rs),
               keysort(Decorated,Sorted),
               numerate(Sorted,1).

numerate([],_).
numerate([_-N|Rest],N) :- N1 is N + 1, numerate(Rest,N1).

...This computes the rank order of a list of elements. For example rank([40,20,50,10],L). unifies L with [3,2,4,1], since 40 is the third largest element, etc.

Partition a list numerically?

Submitted by Greg Buchholz
on June 9, 2009 - 11:13pm

Over on the Haskell Cafe mailing list, the topic of which of the following two definitions was better came up:

buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns


...or...

takeList :: [Int] -> [a] -> [[a]]
takeList [] _         =  []
takeList _ []         =  []
takeList (n : ns) xs  =  head : takeList ns tail
     where (head, tail) = splitAt n xs

...with various parties declaring the first example as "too smart", and others claiming that the second example is newbie level code. Well I'm much too lazy to try to reason out what those snippets might do at a glance. But the type signature was a pretty big hint as to what the intent was. So I fired up

Non-ugly average in Haskell

Submitted by Greg Buchholz
on November 8, 2008 - 12:01am

data E a b = L (E a b) | R b deriving (Show)

fold f acc [] = R acc                      
fold f acc (x:xs) = let x' = f acc x 
                    in x' `seq` (L $ fold f x' xs)

lift2 f = \x y -> par_eval x y
    where par_eval   (L x)   (L y) = par_eval x y
          par_eval x@(R _)   (L y) = par_eval x y
          par_eval   (L x) y@(R _) = par_eval x y
          par_eval   (R x)   (R y) = R $ f x y

lift1 f (L x) = lift1 f x
lift1 f (R x) = R (f x)

sum' xs = fold (+) 0 xs
len' xs = fold (\x y->succ x) 0 xs
avg  xs =  (sum' xs) / (len' xs)

main = print $ avg [1..1e7]

instance Eq b => Eq (E a b) where
    a == b = case (lift2 (==) a b) of (R x) -> x

instance Num b => Num (E a b) where
   (+) = lift2 (+)
   (*) = lift2 (*)
   fromInteger = R . fromInteger
   abs = lift1 abs 
   signum = lift1 signum

instance Fractional b => Fractional (E a b) where
   (/) = lift2 (/)
   fromRational = R . fromRational

Entering unicode

Submitted by Greg Buchholz
on November 23, 2007 - 8:57pm

Here's the configuration file I use to help me enter some of the fun mathematical unicode characters with vim. The commands were borrowed from TeX...

imap jj <ESC>
imap \div ÷
imap \times ×
imap \sum ∑
imap \int ∫
imap \oint ∮
imap \angle ∠
imap \forall ∀
imap \exists ∃
imap \partial ∂
imap \prod ∏
imap \infty ∞
imap \pm ±
imap \sqrt √
imap \circ ∘
imap \Re ℛ
imap \Im ℑ

Misc. ray tracers

Submitted by Greg Buchholz
on October 10, 2007 - 5:01pm


By popular demand, here's the more web accessible versions of a couple of simple ray tracers that I quickly cranked out in Perl and Haskell. Along with the respective source code.

It takes a POV-like scene file, and spits out a *.ppm file onto STDOUT.

Cellular Automata

Submitted by Greg Buchholz
on March 8, 2007 - 6:15pm

After seeing a cellular automata simulator in F#, I thought I'd make a more general version with Perl/TK which was also shorter. Invoke with a numeric argument on the command line to see automata other than rule 30 (e.g. 90, 110).

SWI-Prolog and Unicode.

Submitted by Greg Buchholz
on February 15, 2007 - 2:17pm

% fun with SWI-Prolog and Unicode.  Try some queries like... 
% Ans ≔ ∫x d x.
% Ans ≔ ∫ 2 + x^3 d x.

:- encoding(utf8).
:- op(699, xfy,).
:- op(600, fx,).
:- op(510, xfx, d).
:- op(200, xf, ²).

A+B ≔ ∫ Y+Z d X :- A ≔ ∫ Y d X, B ≔ ∫ Z d X. 
C*A ≔ ∫ C*Y d X :- free(C,X), A ≔ ∫ Y d X.
C*X ≔ ∫ C d X   :- free(C,X).
X² / 2 ≔ ∫ X d X.
X^N1/N1 ≔ ∫ X^N d X :- free(N,X), N =\= -1, N1 is N + 1. 
(log(A*X+B)/A) ≔ ∫ 1/(A * X + B) d X :- free(A,X),free(B,X).
(exp(A*X+B)/A) ≔ ∫ exp(A*X+B) d X    :- free(A,X), free(B,X).E d X ≔ ∫ E d X.

free(C,X) :- \+ bound(C,X).

bound(X,X).
bound(A+B,X) :- bound(A,X); bound(B,X).
bound(A-B,X) :- bound(A,X); bound(B,X).
bound(A*B,X) :- bound(A,X); bound(B,X).
bound(A/B,X) :- bound(A,X); bound(B,X).
bound(A^B,X) :- bound(A,X); bound(B,X).

Breaking free

Submitted by Greg Buchholz
on January 4, 2007 - 11:27pm

If you really want to break free from the von Neumann bottleneck , grab yourself an FPGA starter kit and start playing with Verilog or VHDL. FPGAs are quite interesting now that features like hardware multipliers are becoming more widespread.

Maybe monad in C++

Submitted by Greg Buchholz
on December 18, 2006 - 12:26pm

C++ is a complicated language, but it doesn't have to be that complicated. Here a simple maybe monad implemented in C++...

Planet "Programming Language Dilettante"

Submitted by Greg Buchholz
on December 14, 2006 - 7:12pm

Planet "Programming Language Dilettante". That's one one blog aggregator I'd really like to read.

The more things change the more they stay the same...

Submitted by Greg Buchholz
on December 14, 2006 - 1:25am

After we correct for the algorithmic differences, is there really that much difference between...

fibo 0 = 1 
fibo 1 = 1 
fibo x = fibo (x-1) + fibo (x-2)

Blub is the language you know.

Submitted by Greg Buchholz
on November 20, 2006 - 3:02pm


Pascal Costanza wrote:


But in the general case, dynamic typing and static typing are not compatible. In Common Lisp, there are a lot of cases where you can very conveniently change types at runtime. So a static check of types would be a great burden. Here is my standard example for this:

(defclass person () 
    ((name :initarg :name))) 
 
(let ((p (make-instance 'person :name "Pascal"))) 
    (eval (read)) 
    (setf (slot-value p 'address) "Brussels")) 


There is no chance to see up front whether this program will fail or not, since the user can redefine the class person when (eval (read)) is executed. At that time, the slot 'address could be added to the class person.

I don't see any reason why that's not amenable to static typing...

Memoizing fixed point combinator in C++

Submitted by Greg Buchholz
on November 14, 2006 - 1:41pm

Over on comp.lang.c++ they're discussing memoization of functions. Here's my version of a memoized fix point combinator...

#include<iostream>
#include<map>

std::map<int,int> memo_table;

struct Fix
{
    int (*f)(int,Fix);

    int operator()(int x, Fix g)
    { 
        return (memo_table.find(x) != memo_table.end()) 
               ? memo_table[x]
               : memo_table[x] = g.f(x,g);
    };
};

int fib(int n, Fix f) { return n < 2 ? n : f(n-1,f) + f(n-2,f); }

int main(int argc, char *argv[])
{
    Fix g = {fib};
    std::cout << g(40,g) << std::endl;
    return 0;
}

Type system computation

Submitted by Greg Buchholz
on November 8, 2006 - 3:03pm

Over on comp.lang.lisp we have a comparison of between the type systems of lisp and ML. I don't know enough about ML to know whether it is or isn't up to the challenge, but here's a teaser of how you could go about it in Haskell. First off, we need a data type that knows about the range of possible values for its integral argument. And then we need to be able to exponentiate the range...

Compiling Omega with GHC 6.6

Submitted by Greg Buchholz
on October 24, 2006 - 10:59am

Here are the changes I needed to make in order to get Omega to compile with ghc-6.6.

Changlog entry:

18Oct2006  Greg Buchholz 

  * DepthFirstSearch.hs : Changed from using the ST module to Control.Monad.ST
                          and Data.Array.ST
  * Infer2.hs : Modified to use Data.Map instead of deprecated Date.FiniteMap
  * Toplevel.hs : Modified to use Data.Map 
  * Makefile : Get rid of ghc-6.4 specific "-package lang", let "-make"
               figure it out for us.

...and the diffs.