This repository has been archived by the owner. It is now read-only.
A Haskell based awk and sed alternative
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

hwk Build Status MIT licensed

⚠️ Please use Hawk. While hwk is a hacky MVP to test how well Haskell works as text processing language, Hawk is a more mature tool. This repository is no longer maintained by Lukas Martinelli.


hwk tries to demonstrate how a modern Haskell based stream manipulation tool could look like. It is similar to tools like awk or sed. hwk allows compact command sequences that operate on a list of strings. Because Haskell is lazy and has a powerful arsenal of functions, there is no need to invent another DSL and hopefully push people into using functional goodness. hwk also provides a method to store small functions for reuse in environment variables.


# prepend a string to each line
seq 1 10 | hwk 'map ("number " ++)'

# load the negative function into the current environment
eval $(hwk env negative '(0 >)')

# sum all negative numbers
# the ints function transforms a list of strings into a list of ints
seq -100 100 \
  | hwk '\lines -> filter negative $ ints lines' \
  | hwk '\lines -> sum $ ints lines'

# get first two columns of tsv file
# `cabal install split` to use the library for splitting lists
cat data.tsv |
  | hwk '\lines -> map (take 2) $ map (splitOn "\t") lines'

The argument passed to hwk must be a valid Haskell statement. It should always return a function that takes a list of strings and returns either a new list or a single element. The hwk env command loads the statement into the environment with the specified function name for later reuse.


To install hwk locally you need Haskell and the stack build tool. You can build the binary with stack or cabal.

git clone
cd hwk
stack build

# or with cabal
cabal install

What does hwk do?

  • hwk will generate code and execute it under runhaskell.
  • hwk will try to lookup functions in the passed environment variables.
  • hwk tries to convert the different result types into a list of strings [String].
  • hwk provides additional functions that help with converting streams.

Supported return types

The hwk statement can return the following types.

  • [String]
  • [[String]]
  • [Integer]
  • String
  • Integer

What happens under the Hood?

The hwk code above can be translated directly into a valid Haskell program.

ints = map (\l -> read l :: Int)
hwk = \lines -> filter (0 >) $ ints lines

main = do
    contents <- getContents
    mapM_ putStrLn $ map (\r -> show r) $ hwk $ lines contents

The second hwk 'foldl (+) 0' command will translate to.

ints = map (\l -> read l :: Int)
hwk = \lines -> foldl (+) 0 $ ints lines

main = do
    contents <- getContents
    mapM_ putStrLn $ map (\r -> show r) $ hwk $ lines contents