Skip to content

Instantly share code, notes, and snippets.

@ruthenium
Created September 15, 2012 23:13
Show Gist options
  • Save ruthenium/3730291 to your computer and use it in GitHub Desktop.
Save ruthenium/3730291 to your computer and use it in GitHub Desktop.
Convert a string to CamelCase, mixedCase or under_score just like they do in ruby zucker, but in haskell. Not pure strings and lists, POSIX-Regex approach.
module Main where
import Data.Char (toUpper, toLower)
{- | POSIX Regex approach. -}
import Text.Regex (mkRegex, subRegex, matchRegexAll, Regex)
------------------------------------------------------------------------------
{- | Transforms first element of the 'String' using the function given. -}
transformFst :: (Char -> Char) -> String -> String
transformFst _ "" = ""
transformFst f (x:xs) = f x:xs
------------------------------------------------------------------------------
------------------------------------------------------------------------------
{- | Converts CamelCase or mixedCase 'String' to snake_string.
POSIX Regex approach.
Due to the POSIX Regex syntax limitations, this still needs an extra
case because the first character of the result could be an underscore.
-}
toSnake :: String -> String
toSnake = downcase . go
where
downcase = map toLower
go s = case subRegex (mkRegex "[A-Z]") s "_\\0" of
('_':xs) -> xs
x -> x
------------------------------------------------------------------------------
------------------------------------------------------------------------------
{- | Converts snake_string to mixedCase 'String'.
Uses a custom simple subRegex variant, which accepts a transforming
function as an argument, and applies it to all recursively found
matches in a 'String' given.
NOTE: The regular expression used as a matcher will not match a
trailing \"_\" characters, so a 'String' like "\foo_\" will result in
a \"Foo_\" return value.
-}
toMixed :: String -> String
toMixed = subRegex' (mkRegex "_[a-zA-Z]+") go
where
subRegex' :: Regex -> (String -> String) -> String -> String
subRegex' r n s = case matchRegexAll r s of
Nothing -> s
Just (b, m, a, _) -> b ++ n m ++ (subRegex' r n a)
go :: String -> String
go [] = []
go (x:xs) = transformFst toUpper xs
------------------------------------------------------------------------------
------------------------------------------------------------------------------
{- | Converts snake_string to CamelCase 'String'.
Actually it is a combinator which upcases the first letter of a
'String', previously converted to mixedCase.
-}
toCamel :: String -> String
toCamel = (transformFst toUpper) . toMixed
------------------------------------------------------------------------------
------------------------------------------------------------------------------
main = do
print . toMixed $ "was_snake_string"
print . toCamel $ "was_snake_string"
print . toSnake $ "WasCamelCase"
print . toSnake $ "wasMixedCase"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment