URI Escaping in Haskell (or, reinventing the wheel in style)

As part of my efforts to learn more about functional programming in general and Haskell in specific, I chose a small project that was tangentially related to the work I do in my web programming work at Enterity. If anyone out there knows of a built-in for converting from Int to Hex and back again, I'd be much obliged. I didn't see anything skimming the standard libraries via Zvon.org

module Main where

import System.Environment
import Char
import List

main :: IO ()
main = do args <- getArgs
          case ( args !! 0 ) of
              "encode" -> putStrLn ( encode $ concat $ tail args )
              "decode" -> putStrLn ( decode $ head   $ tail args )

-- --------------------------------------

encode :: String -> String
encode str = concat $ map encodeChar str

decode :: String -> String
decode ""     = ""
decode (c:cs) = case c of
        '%'       -> fromHex( take 2 cs ) : decode( drop 2 cs )
        otherwise -> c                    : decode cs

-- --------------------------------------

encodeChar :: Char -> String
encodeChar c =
    case isLegalChar c of
      True      -> c   : ""
      otherwise -> '%' : ( toHex . ord ) c

isLegalChar :: Char -> Bool
isLegalChar c = any (c==) ( [ 'A' .. 'Z' ] ++ ['a' .. 'z'] ++ [ '0'..'9' ] ++ "-_.!~*'()" )

-- --------------------------------------

toHex :: Int -> String
toHex 0 = ""
toHex x =
    let rem = x `mod` 16
        in toHex( ( x-rem ) `div` 16 ) ++ [ toChar rem  ]

fromHex :: String -> Char
fromHex hx =
    let a = fromChar $ head hx
        z = fromChar $ head $ tail hx
        in chr( a * 16  + z )

-- --------------------------------------

toChar :: Int -> Char
toChar x = ( [ '0' .. '9' ] ++ [ 'a' .. 'f' ] ) !! x

fromChar :: Char -> Int
fromChar x = case findIndex (x==) ( [ '0' .. '9' ] ++ [ 'a' .. 'f' ] ) of
                 Nothing -> 0
                 Just y  -> y
Previous
Previous

Explain Yourself (but Don't Repeat Yourself)