Personal tools

Simple Unix tools

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(link)
(update)
Line 9: Line 9:
--
--
-- Some unix-like tools written in simple, clean Haskell
-- Some unix-like tools written in simple, clean Haskell
 +
--
--
--
Line 17: Line 18:
--
--
-
-- First, a useful helper
+
-- First, two helpers
--
--
-
input f = interact (unlines . f . lines)
+
io f = interact (unlines . f . lines)
 +
showln = (++ "\n") . show
--
--
Line 29: Line 31:
-- Sort a file
-- Sort a file
--
--
-
sort' = input sort
+
sort' = io sort
 +
 
 +
--
 +
-- remove duplicate lines from a file (like uniq)
 +
--
 +
uniq = io nub
--
--
-
-- Reverse a file (tac)
+
-- repeat the input file infintely
--
--
-
tac = input reverse
+
rpt = interact cycle
--
--
-- Return the head -10 line of a file
-- Return the head -10 line of a file
--
--
-
head' = input $ take 10
+
take' = io (take 10)
--
--
-- Remove the first 10 lines of a file
-- Remove the first 10 lines of a file
--
--
-
drop' = input $ drop 10
+
drop' = io (drop 10)
 +
 
 +
--
 +
-- Return the head -1 line of a file
 +
--
 +
head' = io (return . head)
--
--
-- Return the tail -1 line of a file
-- Return the tail -1 line of a file
--
--
-
tail' = input $ (:[]) . last
+
tail' = io (return . last)
 +
--
 +
-- Reverse lines in a file (tac)
--
--
-
-- remove duplicate lines from a file (like uniq)
+
tac = io reverse
 +
 
 +
--
 +
-- Reverse characters on each line (rev)
--
--
-
uniq = input nub
+
rev = io (map reverse)
 +
 
 +
--
 +
-- Reverse words on each line
 +
--
 +
revw = io $ map (unwords. reverse . words)
 +
 
 +
--
 +
-- Count number of characters in a file (like wc -c)
 +
--
 +
wc_c = interact (showln . length)
 +
 
 +
--
 +
-- Count number of lines in a file, like wc -l
 +
--
 +
wc_l = interact (showln . length . lines)
 +
 
 +
--
 +
-- Count number of words in a file (like wc -w)
 +
--
 +
wc_w = interact (showln . length . words)
--
--
-- double space a file
-- double space a file
--
--
-
space = input $ intersperse ""
+
space = io (intersperse "")
--
--
-
-- repeat the input file infinitely
+
-- undo double space
--
--
-
rpt = interact cycle
+
unspace = io $ filter (not.null)
--
--
-- remove the first occurence of the line "str"
-- remove the first occurence of the line "str"
--
--
-
remove = input $ delete "str"
+
remove = io (delete "str")
--
--
-- make a file all upper case
-- make a file all upper case
--
--
-
upper = interact $ map toUpper
+
upper = interact (map toUpper)
--
--
-- remove leading space from each line
-- remove leading space from each line
--
--
-
clean = input $ map (dropWhile isSpace)
+
clean = io $ map (dropWhile isSpace)
--
--
-
-- join lines of a file
+
-- remove trailing whitespace
--
--
-
join = input $ (:[]) . concat
+
clean' = io (map f)
 +
where f = reverse . dropWhile isSpace . reverse
--
--
-
-- Translate the letter 'e' to '*', like tr 'e' '*' (or y// in sed)
+
-- delete leading and trailing whitespace
--
--
-
y = interact $ map f
+
clean'' = io $ map (f . f)
-
where f 'e' = '*'
+
where f = reverse . dropWhile isSpace
-
f c = c
+
 
--
--
-
-- Filter the letter 'e' from a file, like tr -d 'e'
+
-- insert blank space at beginning of each line
--
--
-
tr = interact $ filter (/= 'e')
+
blank = io $ map (s ++)
 +
where s = replicate 8 ' '
--
--
-
-- Count number of characters in a file (like wc -c)
+
-- join lines of a file
--
--
-
wc_c = interact $ show . length
+
join = io (return . concat)
--
--
-
-- Count number of lines in a file, like wc -l
+
-- Translate the letter 'e' to '*', like tr 'e' '*' (or y// in sed)
--
--
-
wc_l = interact $ show . length . lines
+
y = interact (map f)
-
 
+
where f 'e' = '*'
 +
f c = c
--
--
-
-- Count number of words in a file (like wc -w)
+
-- Filter the letter 'e' from a file, like tr -d 'e'
--
--
-
wc_w = interact $ show . length . words
+
tr = interact $ filter (/= 'e')
--
--
-- grep lines matching "^foo" from a file
-- grep lines matching "^foo" from a file
--
--
-
grep = input $ filter (isPrefixOf "foo")
+
grep = io $ filter (isPrefixOf "foo")
--
--
-- grep lines that don't match "^foo" (grep -v)
-- grep lines that don't match "^foo" (grep -v)
--
--
-
grep_v = input $ filter (not . isPrefixOf "foo")
+
grep_v = io $ filter (not . isPrefixOf "foo")
--
--
-- number each line of a file
-- number each line of a file
--
--
-
num = input $ zipWith (printf "%3d %s") [1::Int..]
+
num = io $ zipWith (printf "%3d %s") [(1::Int)..]
--
--
-
-- Compute a simple hash of a file
+
-- Compute a simple cksum of a file
--
--
-
cksum = interact $ printf "%u\n" . foldl' k 5381
+
cksum = interact $ showln . foldl' k 5381
-
where k h c = h * 33 + fromIntegral (ord c) :: Int
+
where k h c = h * 33 + ord c
 +
 
</haskell>
</haskell>
 +
'''Where to now?'''
'''Where to now?'''

Revision as of 13:54, 23 September 2006

Simple unix tools written in Haskell.

This is intended as a beginners tutorial for learning Haskell from a "Lets just solve things already!" point of view. The examples should help give a flavour of the beauty and expressiveness of Haskell programming.

--
-- Some unix-like tools written in simple, clean Haskell
--
--
 
import Data.List
import Data.Char
import System.IO
import Text.Printf
 
-- 
-- First, two helpers
--
io f    = interact (unlines . f . lines)
showln  = (++ "\n") . show
 
--
-- The 'cat' program
--
cat     = interact id
 
--
-- Sort a file
--
sort'   = io sort
 
--
-- remove duplicate lines from a file (like uniq)
--
uniq    = io nub
 
-- 
-- repeat the input file infintely 
--
rpt     = interact cycle
 
--
-- Return the head -10 line of a file
--
take'   = io (take 10)
 
--
-- Remove the first 10 lines of a file
--
drop'   = io (drop 10)
 
--
-- Return the head -1 line of a file
--
head'   = io (return . head)
 
--
-- Return the tail -1 line of a file
--
tail'   = io (return . last)
 
-- 
-- Reverse lines in a file (tac)
--
tac     = io reverse
 
--
-- Reverse characters on each line (rev)
--
rev     = io (map reverse)
 
--
-- Reverse words on each line
--
revw    = io $ map (unwords. reverse . words)
 
--
-- Count number of characters in a file (like wc -c)
--
wc_c    = interact (showln . length)
 
--
-- Count number of lines in a file, like wc -l
--
wc_l    = interact (showln . length . lines)
 
--
-- Count number of words in a file (like wc -w)
--
wc_w    = interact (showln . length . words)
 
--
-- double space a file
--
space   = io (intersperse "")
 
-- 
-- undo double space
--
unspace = io $ filter (not.null)
 
--
-- remove the first occurence of the line "str"
--
remove  = io (delete "str")
 
--
-- make a file all upper case
--
upper   = interact (map toUpper)
 
--
-- remove leading space from each line
--
clean   = io $ map (dropWhile isSpace)
 
--
-- remove trailing whitespace
--
clean'  = io (map f)
    where f = reverse . dropWhile isSpace . reverse
 
--
-- delete leading and trailing whitespace
--
clean'' = io $ map (f . f)
    where f = reverse . dropWhile isSpace
 
--
-- insert blank space at beginning of each line
--
blank   = io $ map (s ++)
    where s = replicate 8 ' '
 
--
-- join lines of a file
--
join    = io (return . concat)
 
--
-- Translate the letter 'e' to '*', like tr 'e' '*' (or y// in sed)
--
y       = interact (map f)
    where f 'e' = '*'
          f  c  =  c
--
-- Filter the letter 'e' from a file, like tr -d 'e'
--
tr      = interact $ filter (/= 'e')
 
--
-- grep lines matching "^foo" from a file
--
grep    = io $ filter (isPrefixOf "foo")
 
--
-- grep lines that don't match "^foo" (grep -v)
--
grep_v  = io $ filter (not . isPrefixOf "foo")
 
--
-- number each line of a file
--
num     = io $ zipWith (printf "%3d %s") [(1::Int)..]
 
--
-- Compute a simple cksum of a file
--
cksum   = interact $ showln . foldl' k 5381
    where k h c = h * 33 + ord c


Where to now?