Simple Unix commandline tools written in Haskell.

This is intended as a beginner’s tutorial for learning Haskell from a “Let’s just solve things already!” point of view. The examples should help give a flavor of the beauty and expressiveness of Haskell programming.

These functions can be executed as one liners from a shell. For example, to use the Haskell version of ‘wc’:

   $ cat file.txt | ghc -e 'wc_l' UnixTools.hs

Or, one could define ‘main’ to be a chosen tool/function (add a line to the effect that “main = wc_l”) and then compile the tool with

   $ ghc --make UnixTools.hs
import Control.Monad.Instances
import Data.List
import Data.Char
import Data.Maybe
import Text.Printf
import System.Environment

-- First, two helpers
io f = interact (unlines . f . lines)

showln  = (++ "n") . show

-- remove duplicate lines from a file (like uniq)
uniq    = nub

-- repeat the input file infinitely
rpt     = cycle

-- Return the head -10 line of a file
take'   = take 10

-- Remove the first 10 lines of a file
drop'   = drop 10

-- Return the head -1 line of a file
head'   = head

-- Return the tail -1 line of a file
tail'   = last

-- return the last ten lines of a file
tail10  = drop =<< subtract 10 . length

-- Reverse lines in a file (tac)
tac     = reverse

-- Reverse characters on each line (rev)
rev     = map reverse

-- Reverse words on each line
rev_w   = map (unwords . reverse . words)

-- Count number of characters in a file (like wc -c)
wc_c    = showln . length

-- Count number of lines in a file, like wc -l
wc_l    = showln . length . lines

-- Count number of words in a file (like wc -w)
wc_w    = showln . length . words

-- double space a file
space   = intersperse ""

-- undo double space
unspace = filter (not.null)

-- remove the first occurrence of the line "str"
remove  = delete

-- make a string all upper case
upper   = map toUpper

-- remove leading space from each line
clean   = map (dropWhile isSpace)

-- remove trailing whitespace
clean'  = map (reverse . dropWhile isSpace . reverse)

-- delete leading and trailing whitespace
clean'' = map (f . f)
    where f = reverse . dropWhile isSpace

-- insert blank space at beginning of each line
blank   = map (s ++)
     where s = replicate 8 ' '

-- join lines of a file
join = return . concat

-- Translate the letter 'e' to '*', like tr 'e' '*' (or y// in sed)
tr a b = interact (map f)
    where f c = if c == a then b else c

-- Delete characters from a string.
tr_d a = tr a ' '

-- grep lines matching "^foo" from a file
grep = filter (isPrefixOf "foo")

-- grep lines that don't match "^foo" (grep -v)
grep_v  = filter (not . isPrefixOf "foo")

-- number each line of a file
num  = zipWith (printf "%3d %s") [(1::Int)..]

-- Compute a simple cksum of a file
cksum   =  foldl' k 5381
   where k h c = h * 33 + ord c
About these ads