Recommended workflows for day-to-day Haskell development with hx.
Starting Your Day
Check Environment
# Verify everything is set up
hx doctor
# Update package index periodically
cabal updateSync Dependencies
If you pulled changes:
git pull
hx syncDevelopment Workflows
Test-Driven Development
The TDD loop with watch mode:
hx watch testWorkflow:
- Write a failing test
- Save → tests run automatically
- Write implementation
- Save → tests pass
- Refactor
- Save → tests still pass
Type-Driven Development
Fast type checking feedback:
hx watch checkWorkflow:
- Write type signatures first
- Save → see type errors
- Implement functions
- Save → types check
Interactive Development
REPL-driven workflow:
hx replghci> import MyModule
ghci> :type myFunction
ghci> myFunction testInput
-- Make changes to file
ghci> :reload
ghci> myFunction testInputBuild and Run
For application development:
hx watch runAutomatically rebuilds and restarts on changes.
Feature Development
Starting a New Feature
# Create feature branch
git checkout -b feature/new-feature
# Add dependencies if needed
hx add new-package
# Update lockfile
hx lock
# Start development
hx watch testAdding a New Module
Create the file:
touch src/MyProject/NewModule.hsAdd to
.cabal:exposed-modules: MyProject.NewModuleImplement:
module MyProject.NewModule where -- implementationAdd tests:
-- test/MyProject/NewModuleSpec.hs module MyProject.NewModuleSpec where import Test.Hspec import MyProject.NewModule spec :: Spec spec = do describe "newFunction" $ do it "does something" $ do -- test
Adding Dependencies
# Add to project
hx add text containers
# Add test-only dependencies
hx add --dev hspec QuickCheck
# Update lockfile
hx lock
# Verify
hx build
hx testCode Quality
Before Committing
# Format code
hx fmt
# Check for issues
hx lint
# Run tests
hx test
# Type check
hx checkUsing Pre-commit Hooks
Create .git/hooks/pre-commit:
#!/bin/sh
set -e
echo "Checking formatting..."
hx fmt --check
echo "Running linter..."
hx lint
echo "Running tests..."
hx testMake executable:
chmod +x .git/hooks/pre-commitDebugging
Adding Debug Output
import Debug.Trace
myFunction x =
trace ("myFunction called with: " ++ show x) $
-- implementationRun:
hx runUsing GHCi Debugger
hx replghci> :set -fbreak-on-exception
ghci> myFunction input
*** Exception: ...
ghci> :back
ghci> :listVerbose Build Output
hx build --verboseShows full GHC command and output.
Performance Work
Profiling
# Build with profiling
hx build --ghc-options="-prof -fprof-auto"
# Run with profiling
hx run -- +RTS -p -RTS
# View profile
cat my-app.profBenchmarking
# Always use release mode
hx bench --releaseRelease Preparation
Pre-Release Checklist
# Update version in .cabal
# Update CHANGELOG.md
# Ensure lockfile is current
hx lock
# Run full test suite
hx test
# Build release
hx build --release
# Generate docs
hx doc
# Check everything
hx doctorCreating a Release
# Commit changes
git add -A
git commit -m "Release v1.0.0"
# Tag
git tag v1.0.0
# Push
git push --tagsTeam Workflows
Code Review
Before submitting PR:
hx fmt
hx lint
hx test
hx lock --check # Ensure lockfile is currentUpdating Dependencies
# Check what's outdated
hx outdated
# Update specific packages
hx update aeson text
# Update all
hx update
# Run tests
hx test
# Commit lockfile changes
git add hx.lock
git commit -m "Update dependencies"Handling Merge Conflicts
If hx.lock conflicts:
# Take one side
git checkout --ours hx.lock
# Regenerate
hx lock
# Verify
hx build
hx test
# Commit
git add hx.lock
git commitEditor Integration
VS Code
Install “Haskell” extension. Recommended settings:
{
"haskell.formattingProvider": "ormolu",
"editor.formatOnSave": true
}Use integrated terminal for:
hx watch testVim/Neovim
Split workflow:
:split | terminal hx watch testEmacs
(defun hx-watch-test ()
(interactive)
(async-shell-command "hx watch test"))See Also
- hx watch — Watch mode
- hx repl — Interactive development
- Formatting & Linting — Code quality