[Haskell-cafe] Help converting Perl to Haskell

Jason Dagit dagit at codersbase.com
Tue Oct 21 23:33:32 EDT 2008


I'm not very perl literate, but I want to convert a perl script to
Haskell.  This bit of perl is part of darcs' test suite.  I was hoping
to make it "more portable" by writing it in Haskell.  By more portable
I mean, works in windows without cygwin/mingw/msys and avoids the need
for perl also.  Depending on a Haskell compiler seems reasonable since
darcs is written in Haskell :)

Correct me if I'm wrong, but if I want to make this work on windows I
can't use System.Posix, right?  If so, what is the portable way to set
environment variables?  I see[1] that getEnv exists in
System.Environment, but setEnv is in System.Posix.Env.  I looked in
System.Win32 and I didn't see anything that looked like it would
manipulate environment variables.  Will I have to use
System.Process.runProcess on Win32?  I'd like this to work on ghc 6.6
and System.Process looks new?

Another thing I noticed is that System.Directory doesn't give me a way
to exactly emulate this bit of perl:
mkdir 'test_output', 0750;

If I use System.Directory.setPermissions, then I think the closest I
can approximate those permissions is:
setPermissions "test_output" (Permissions {readable = True, writable =
True, executable = True, searchable = True})

Which just makes sure it has the 7 for user, but doesn't seem to
change the other permissions.  Maybe that won't matter in practice,
but I wanted to make it as close as possible to minimize unforeseen
problems.  I guess I could write a function that uses setPermissions
on win32 and uses the appropriate thing from System.Posix when not on

Below is the full perl script if you want to see what I'm starting
from.  I think most of it should be easy to replace.

#!/usr/bin/perl -w

# Run each of the shell tests, capturing the output, and reporting passed
# or failed.

use Cwd;
use File::Find;

# Place to put test output to avoid cluttering test/
mkdir 'test_output', 0750;

# Override the users default .darcs settings
$ENV{HOME} = cwd();
mkdir '.darcs';
system 'echo ALL --ignore-times >> .darcs/defaults';
# Used for finding darcs, but may not be defined by the shell
$ENV{PWD} = cwd();

# Put the right darcs first in PATH
my $darcspath="$ENV{HOME}/..";
if ($ENV{DARCS}) {
  # User has asked for a particular darcs...
  my $actualdarcs=`which $ENV{DARCS}`;
  my $darcspath=`dirname "$actualdarcs"`;
$ENV{PATH} = "$darcspath:$ENV{PATH}";

# Some environment variables can act as defaults that we don't want
$ENV{EMAIL} = $ENV{DARCS_EMAIL} = 'tester';

# These two environment variables will turn off darcs' "Christmas mode".
# It will make the tests run a tad faster, and make darcs' output
# independent of the testing systems locale and environment.

my $OK = 1;
my @Failures;
my @Passes;

`which bash`;
if( $? != 0 ) {
    die "You need bash to run the shell tests!"

for my $test (@ARGV) {
    my $test_out = "test_output/$test.out";

    printf "Running %-40s", "$test ...";

    my $output = `bash $test 2>&1`;

    if( $? == 0 ) {
        push @Passes, $test;
        print " passed.\n";
    else {
        $OK = 0;
        push @Failures, $test;

        print " FAILED!\n";
        print "Output from failed $test:\n$output";
    # give ourselves write permissions to every file in a tmp dir
    # (in case a script sets permissions and fails to clean up
    # after itself)
    my @tmpdirs = glob("tmp* temp*");
    if (@tmpdirs > 0) {
      find (sub { chmod 0755, $_; }, @tmpdirs);

my $CWD = cwd();
if ($CWD =~ /bugs/ && $#Passes >= 0) {
  print "Some tests passed:\n";
  print "\t$_\n" for @Passes;
if ($OK) {
    print "All tests successful!\n";
else {
    print "TESTS FAILED!\n";
    print "\t$_\n" for @Failures;

# Exit with non-zero if anything failed.
exit !$OK;


[1] http://www.haskell.org/ghc/docs/latest/html/libraries/

More information about the Haskell-Cafe mailing list