String Formatting in Haskell

Our example demonstrates string formatting in Haskell. Here’s the full source code:

import Text.Printf
import System.IO (hPutStrLn, stderr)

data Point = Point { x :: Int, y :: Int }

main :: IO ()
main = do
    let p = Point 1 2

    -- Haskell doesn't have a direct equivalent to Go's %v, but we can use show
    putStrLn $ "struct1: " ++ show p

    -- Haskell doesn't have a %+v equivalent, but we can define a custom show instance
    putStrLn $ "struct2: " ++ "Point {x = " ++ show (x p) ++ ", y = " ++ show (y p) ++ "}"

    -- Haskell doesn't have a %#v equivalent, but we can use show again
    putStrLn $ "struct3: " ++ show p

    -- For type, we can use :t in GHCi, but here we'll just print it
    putStrLn $ "type: Point"

    -- Formatting booleans
    putStrLn $ "bool: " ++ show True

    -- Formatting integers
    putStrLn $ "int: " ++ show 123

    -- Binary representation
    printf "bin: %b\n" (14 :: Int)

    -- Character from integer
    putStrLn $ "char: " ++ [toEnum 33 :: Char]

    -- Hexadecimal
    printf "hex: %x\n" (456 :: Int)

    -- Floating point numbers
    printf "float1: %f\n" (78.9 :: Float)

    -- Scientific notation
    printf "float2: %e\n" (123400000.0 :: Float)
    printf "float3: %E\n" (123400000.0 :: Float)

    -- String formatting
    putStrLn $ "str1: " ++ show "\"string\""

    -- Double-quoted strings
    putStrLn $ "str2: " ++ show "\"string\""

    -- Hexadecimal representation of string
    putStrLn $ "str3: " ++ concatMap (printf "%02x") "hex this"

    -- Pointer representation (not applicable in Haskell)
    putStrLn "pointer: Not applicable in Haskell"

    -- Width specification for integers
    printf "width1: |%6d|%6d|\n" (12 :: Int) (345 :: Int)

    -- Width and precision for floats
    printf "width2: |%6.2f|%6.2f|\n" (1.2 :: Float) (3.45 :: Float)

    -- Left-justified floats
    printf "width3: |%-6.2f|%-6.2f|\n" (1.2 :: Float) (3.45 :: Float)

    -- Width for strings
    printf "width4: |%6s|%6s|\n" "foo" "b"

    -- Left-justified strings
    printf "width5: |%-6s|%-6s|\n" "foo" "b"

    -- Sprintf equivalent
    let s = printf "sprintf: a %s" "string"
    putStrLn s

    -- Writing to stderr
    hPutStrLn stderr "io: an error"

To run this program, save it as string-formatting.hs and use runhaskell:

$ runhaskell string-formatting.hs
struct1: Point {x = 1, y = 2}
struct2: Point {x = 1, y = 2}
struct3: Point {x = 1, y = 2}
type: Point
bool: True
int: 123
bin: 1110
char: !
hex: 1c8
float1: 78.900000
float2: 1.234000e8
float3: 1.234000E8
str1: "\"string\""
str2: "\"string\""
str3: 6865782074686973
pointer: Not applicable in Haskell
width1: |    12|   345|
width2: |  1.20|  3.45|
width3: |1.20  |3.45  |
width4: |   foo|     b|
width5: |foo   |b     |
sprintf: a string
io: an error

Note that Haskell’s string formatting capabilities are different from Go’s. We’ve used a combination of putStrLn, printf, and show to achieve similar results. The Text.Printf module provides printf-style formatting, but it’s not as feature-rich as Go’s formatting. For more complex formatting needs, you might want to consider using libraries like text-format or formatting.