Adjunct to C++ in Haskell
Saturday, October 3, 2009 at 10:20PM So while writing my third installment of my review of the book "Elements of Programming" I went about writing all the solutions in C++. I found that while I was at it, I was thinking about how more and more awkward programming with object oriented approaches was becoming. The 'C' way isn't helping at all too. So before I posted my entry, I already set up Haskell on Alice and hacked away at my Haskell implementation of the same solution in C++. This blog post is about that experience.
First, I would like to give a backgrounder on what the problem I'm trying to solve is. It's a simple coordinate filtering application that takes 2d points from a data source (a file more precisely) and prints out those that are within a certain distance from a given point. This is a simple enough problem which I would definitely ask programmers to code up in an interview in front of a computer -- it's not too complex, and there are lots of ways to do it.
Next, I proceeded to code up in Haskell what I would describe in my C++ implementation as a Coordinate. Here's the code that follows, explained later:
-- This defines the Coordinate Type Class
module Coordinates (Coordinate, distance, toString) where
-- Each coordinate is basically two Doubles and we
-- want to be able to reach into a coordinate to pull
-- the x and y components of an instance.
data Coordinate = Coordinate {
xcoord :: Double
, ycoord :: Double
} deriving (Eq, Show)
-- Compute the distance between two coordinates
distance :: Coordinate -> Coordinate -> Double
distance c1 c2 = sqrt $ x_dist * x_dist + y_dist * y_dist
where x_dist = abs $ xcoord c1 - xcoord c2
y_dist = abs $ ycoord c1 - ycoord c2
-- Turn a coordinate into a String that can be
-- printed.
toString :: Coordinate -> String
toString c = "[" ++ show (xcoord c) ++ "," ++ show (ycoord c) ++ "]"
So in the above listing I have a module called (aptly) Coordinate (which is also saved as Coordinate.hs). There are two functions -- distance and toString which do precisely what they describe. It's not a lot of code and you can liken this to a type definition in C++ where you have a class Coordinate which has two member variables accessible through 'xcoord' and 'ycoord' external functions (maybe friends). You usually would also put this in another file in C++, maybe a .hpp file for the structure declaration and a .cpp file for the structure definition.
That's straight forward enough too, the distance function is the mathematical definition. Maybe you can remove the call to the abs function and it wouldn't change the function.
That is the easy part. The other part is the part where I find out all the coordinates from the file which are within a certain distance to a source coordinate. That code listing is what follows:
import Coordinates
import qualified Data.ByteString.Lazy.Char8 as L
import System (getArgs)
import Data.Maybe
import System.IO
readCoordinate :: L.ByteString -> Maybe Coordinate
readCoordinate str =
case L.split ' ' str of
[x,y] -> Just $ Coordinate (read (L.unpack x) ) (read (L.unpack y) )
_ -> Nothing
printQualified :: Double -> (Coordinate,Double) -> IO ()
printQualified threshold (coordinate, distance) =
if distance < threshold then
putStrLn $ toString coordinate ++ " " ++ show distance
else
return ()
main = do
args <- getArgs
case args of
[input_filename,x,y,threshold]
-> do
contents <- L.readFile $ input_filename
let coordinates = map fromJust $ map readCoordinate (L.lines contents)
distances = map (distance (Coordinate (read x) (read y))) $ coordinates
mapM_ (printQualified (read threshold) ) (zip coordinates distances)
_ -> putStrLn "We need the input filename, source x, source y, and threshold distance as the arguments."
And that's it folks. The interesting part is the lines which go:
let coordinates = map fromJust $ map readCoordinate (L.lines contents)
distances = map (distance (Coordinate (read x) (read y))) $ coordinates
mapM_ (printQualified (read threshold) ) (zip coordinates distances)
Where basically, it says "print those qualified within a threshold distance all coordinates and their distances zipped together". Which by the way, is the gist of the application as well.
I'm actually beginning to like Haskell as a programming language that lets me describe what I'm thinking in a closer manner than it does with C++. I definitely see myself writing more and more of these kinds of applications in Haskell and maybe venture into doing visualization using different bindings already available in Haskell. I might even do GUI programming in Haskell someday. Stay tuned, I'm beginning to like this Haskell thing.
haskell in
Personal,
Technology 

Reader Comments