Posts tagged ‘haskell’

Python has optional arguments…

I think the answer to this is currying. It’s not quite as cute:

foo a b = ...

Later becomes

foo = foo1 const
foo1 c a b = ...

If you don’t like sticking c at the front you’ll have to use lambda:

foo a b = \ a b -> foo 1 a b const
foo1 a b c = ...

In some cases you can use flip I suppose. Someone who knows haskell better than me might have better solutions to it…

Oh yes, I have to say that requiring an account is not inviting casual commenters…

C and Haskell sitting in a tree…

A few days ago I thougth I’d take a look at calling C functions from haskell. I wrote up the following set of files:

foo.h:

int foo(int i);

foo.c:

int
foo(int i)
{
    return i * i;
}

Foo.hs:

module Main where

import Foreign.C.Types

main = do
    r <- foo 2
    putStrLn $ show r

foreign import ccall safe "foo.h foo" foo :: CInt -> IO CInt

Compiling the C file was of course no problem:

% gcc -c foo.c

The haskell file offered some resistance:

% ghc -c Foo.hs
Foo.hs:9:8: parse error on input `import'

It took me a round on haskell-cafe before I found out that ghc needs to be told to use the foreign function interface, -ffi or -fffi:

% ghc -c -fffi Foo.hs

Linking is a snap after that:

% ghc -o foo foo.o Foo.o
% ./foo
4

It’s also possible to build and link it all in one go:

% ghc --make -fffi -o foo foo.c Foo.hs

Now, that’s pretty nice, however it’d be even nicer to use cabal to do the building. At the same time I decided to put c2hs to use. It seemed to be a lot easier than having to create the import statements manually. I ended up with the following:

csrc/foo.h:

#ifndef _FOO_H_

int foo(int);

#endif

csrc/foo.c:

#include "foo.h"

int
foo(int i)
{
    return i * i;
}

I couldn’t get cabal to accept Foo.chs as the file containing the Main module in my project. So I ended up putting all the relevant code in Foo and then have a dummy Main.

src/Foo.chs:

module Foo where

#include "foo.h"

import Foreign.C.Types

main = do
    r <- {# call foo #} 2
    putStrLn $ show r

Here’s the dummy Main.

src/Main.hs:

module Main where

import qualified Foo

main = Foo.main

The cabal file is rather straight forward. It took me a round on haskell-cafe to find out how to let the compiler know that I need the foreign function interface without putting compiler directives in the source file.

cnh.cabal:

name: cnh
version: 0.1
build-depends: base

executable: cnh
main-is: Main.hs
hs-source-dirs: src
include-dirs: csrc
c-sources: csrc/foo.c
extensions: ForeignFunctionInterface
other-modules: Foo

Nothing special is needed in the Setup.hs:

#! /usr/bin/env runhaskell

import Distribution.Simple
main = defaultMain

Make it executable and you can build in two easy steps:

% ./Setup.hs configure && ./Setup.hs build

Listing files in Haskell

As I promised earlier here’s a post on my playing with files and directories in Haskell. This was a few days ago so I’ve forgotten a few of the twists and turns that took me to the goal. Forgive me for that.

First, my goal was to list all files below a directory, recursively. I was sort of hoping to find something similar to Python’s os.walk(). No such luck!

I found out a few things.

  1. getDirectoryContents returns everything in a directory, including . and ... I needed a filter to remove them:

    isDODD f = not $ (endswith "/." f) || (endswith "/.." f)
    

    (At first I called it isDotOrDotDot but I like isDODD better.)

  2. I also needed to separate out the directories and files from the result of getDirectoryContents:

    listDirs = filterM doesDirectoryExist
    listFiles = filterM doesFileExist
    
  3. getDirectoryContents returns a list of the contents in the directory you point it to. All file names/directory names are relative to that path. That means the next thing I needed was to join paths. I first couldn’t believe that there wasn’t a function to do that. I mean, I can list contents of a directory, I can find out if something’s a file or a directory, but the most basic manipulation of paths isn’t there. At first I simply concatenated strings, but I didn’t worry about making it cross platform or anything. Then I found that Cabal comes with libraries that handles cross-platform issues properly, but that library was “closed”. After moaning asking on haskell-cafe I found FilePath. It’s even packaged for Debian here.

    FilePath.joinPath takes a list of strings to join, while I was only interested in joining two strings at a time:

    joinFN p1 p2 = joinPath [p1, p2]
    

Putting it all together I ended up with the following:

listFilesR :: FilePath -> IO [FilePath]
listFilesR path = let
    isDODD :: String -> Bool
    isDODD f = not $ (endswith "/." f) || (endswith "/.." f)

    listDirs :: [FilePath] -> IO [FilePath]
    listDirs = filterM doesDirectoryExist

    listFiles :: [FilePath] -> IO [FilePath]
    listFiles = filterM doesFileExist

    joinFN :: String -> String -> FilePath
    joinFN p1 p2 = joinPath [p1, p2]

    in do
        allfiles <- getDirectoryContents path
        no_dots <- filterM (return . isDODD) (map (joinFN path) allfiles)
        dirs <- listDirs no_dots
        subdirfiles <- (mapM listFilesR dirs >>= return . concat)
        files <- listFiles no_dots
        return $ files ++ subdirfiles

Fun with Haskell

What better way is there to spend a Saturday than playing with Haskell? I sure don’t know :-)

I do have a goal in mind, but for now I’m mostly fooling around with some file-related stuff.

First, I wanted to wanted to load an entire file and print it on stdout. Basically a primitive cat. I came up with the following main:

main = liftM (!! 0) getArgs >>= catFile >>= mapM_ putStrLn

As you can see I did spend some time thinking about Monads lately. Something that’s especially pressing if one wants to do IO in Haskell since the IO Monad can’t be escaped from. Next catFile (which based on the use above should have the type FilePath -> IO [String]). I did some experimenting and searching in Hoogle among the System.IO functions. I found openFile, hGetContents that would let me open and read the file. I played a bit with that:

catFile fname = do
    hf <- openFile fname ReadMode
    conts <- hGetContents hf
    hClose hf
    return conts

That doesn’t have quite the required type, but that isn’t the only problem. The combination of hGetContents and hClose doesn’t quite work—the file is never read (laziness in action!). I removed the hClose (since the process isn’t very long-lived that doesn’t bother me so much) and I added a lines:

catFile fname = do
    hf <- openFile fname ReadMode
    conts <- hGetContents hf
    return $ lines conts

Then I stumbled on readFile and rewrote it as

catFile fname = do
    content <- readFile fname
    return $ lines content

which can be written even shorter as

catFile fname = readFile fname >>= return . lines

I guess it’s time to explain the reason for returning IO [String] rather than IO String. The latter would have simplified both catFile and main. What I really wanted was to make each line of a file an item in a set. My first thought was to fold it:

catFile "test_file" >>= (\l -> return $ foldr Set.insert Set.empty l)

Which can be re-written in point-free style (I hope I’ve gotten point-free right here):

catFile "test_file" >>= return . foldr Set.insert Set.empty

Then I decided to look into Data.Set and found fromList. My first naïve attempt and my point-free:

catFile "test_file" >>= (\l -> return $ Set.fromList l)
catFile "test_file" >>= return . Set.fromList

Then I reversed my thinking and tried to lift the function into the monad instead:

liftM Set.fromList $ catFile "test_file"

At that point I felt I had somewhat exhausted this particular little playground and went on to listing files and directories, but that’s a story for another post.

Getting real with Haskell

Yesterday I decided to leave the relative safety of solving exercises in tutorials and instead try solving a small problem I had at work. I had pairs of times (points in time, like Wednesday November 8 01:17) and I needed the difference between them. Not a tricky problem by any stretch of the imagination, but I figured I had to start using Haskell at some point. I might as well make this that point.

I started out by playing around with System.Time and System.Locale in gchi. One thing that seemed missing was a function that took a String and tried to interpret it as a CalendarTime. After a mail to Haskell Cafe I discovered MissingH.

I found myself programming top-down, stubbing “sub functions” while trying to get the types of the current function right. It turns out I was “lucky” and there wasn’t many monads involved, but still I did run into some problems with mixing do notation and let, where, and case. In the end I split out those constructs and kept only the most basic syntactical constructs inside the do.

Here’s the end result, not the most functional piece of Haskell code ever seen, but it’s the first time I dip my toes in the sea of Haskell without a tutorial life-west.

module Main where

import System.Locale
import System.Time
import System.Environment
import MissingH.Time.ParseDate

diffAndToString :: CalendarTime -> CalendarTime -> String
diffAndToString s e = 
    let
        sC = toClockTime s
        eC = toClockTime e
        diff = normalizeTimeDiff $ diffClockTimes eC sC
    in
        formatTimeDiff defaultTimeLocale "%R" diff

calcDiff :: String -> String -> Either String String
calcDiff start end =
    let
        -- I had problems using %Y, so I'm using %C%y instead
        sT = parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" start
        eT = parseCalendarTime defaultTimeLocale "%C%y%m%d-%H%M" end
    in
        case (sT, eT) of
        (Nothing, _) -> Left "start time"
        (_, Nothing) -> Left "end time"
        (Just s, Just e) -> Right $ diffAndToString s e

resultString :: String -> String -> String
resultString s e =
    let
        calculatedDiff = calcDiff s e
    in
        case calculatedDiff of
        (Left s) -> "Bad " ++ s
        (Right s) -> s

main :: IO ()
main = do
    args <- getArgs
    putStrLn $ resultString (args !! 0) (args !! 1)