Yes, absolutely! That's one of the beautiful things about Haskell.
You can treat Strings as [Char]. In fact, that's what they are!
In GHCi, type :i String - you get type String = [Char].
You can easily compose functions. There's an operator for that, (.).
So (f . g) x is f (g x).
I would improve the code in a few key ways.
Firstly, make the replaceBlank function more general, so it takes a condition and a replacement function.
Secondly, compose all the functions in a "main" function, as you call it.
But do not name the main function main! That name is reserved for the IO action of a program.
It's also important not to think of the final function as "calling" the other functions.
That is imperative terminology, here, we are applying the function(s).
Also, why does your dropInvalids contain a toUpperStr? You never specified the string to be all uppercase in the end.
Also also, be sure to declare the type of your functions.
In this case, the following would be the correct code:
import Data.Char
dropInvalids :: [Char] -> [Char]
dropInvalids = filter (\x -> isLetter x || isSpace x || isDigit x)
-- isLetter exists
replace' :: (a -> Bool) -> (a -> a) -> [a] -> [a]
replace' _ _ [] = []
replace' f g (x:xs) =
if f x
then g x : replace' f g xs
else x : replace' f g xs
-- To replace one value with another, use replace (== a) (const b).
replaceWith :: (a -> Bool) -> a -> [a] -> [a]
replaceWith f b = replace' f (const b)
replace :: Eq a => a -> a -> [a] -> [a]
replace a b = replace' (== a) (const b)
-- The Eq makes sure you can check for equality.
manipulateString :: [Char] -> [Char]
manipulateString = replace 'A' 'Z' . replace 'a' 'z' . replaceWith isDigit ' ' . replace ' ' '_' . dropInvalids
Answer from schuelermine on Stack OverflowString manipulation haskell - Stack Overflow
Text or String
Haskell String Types
I don't think I'd really call ByteString a string type...it has no semantics for being a string, and really is supposed to encapsulate nothing more meaningful than a list or array (depending on lazy or strict) of bytes. "Converting a string to a bytestring" doesn't really make much sense...what encoding are you encoding it in? The choice is ambiguous and comes down to weird implementation quirks and hacks and doesn't actually make sense in the context of what a String is...and doesn't pay any respect to the semantics of String and so is more or less a meaningless conversion.
Text is actually designed to be a semantic encoding-agnostic container (following unicode standards). It's supposed to be able to understand text as text, regardless of encoding. So, that means that from the encoding functions in Data.Text.Encoding, it can decode encoded bytestrings from different encodings (utf8, utf16, etc., anything you'll probably encounter in the real world) and it can encode to bytestrings from different encodings, as well. Text operations deal with text and are an abstraction over whatever encoding they might be in.
Think of it this way. I have a program that uses a lot of Ints. Should I go in and replace every 4 with "4" :: String? No, that's pretty silly. 4 the Int gives me a powerful API to deal with Ints as Ints -- they can be added, subtracted, multiplied, converted to different numerical formats...if I want to work with integers, I'd use 4 and not "4". "4" to do arithmetic is just silly. Can you imagine fib :: String -> String, which takes a String representing an Int and returns another String representing an Int?
It's the same thing for ByteString and Text. Text represents text in a meaningful way and has an API for manipulating text. But using ByteString to store text is like using "4" to store numbers. It doesn't even make sense to store numbers as strings...there's more than one way! What if you wanted to encode 4 as "four" instead? And there's no API in bytestring to deal with text. It just doesn't represent text...it represents a string of bytes. And ByteString can really mangle your text if you don't pay attention to the implementation detail and exact quirks of the hack you are doing.
String types in Haskell (+ rare ones)
and you must process them correctly,
text-icuwill be indispensable.
Instead of text-icu I can recommend unicode-transforms package:
https://github.com/composewell/unicode-transforms
hk_hooda gave a talk at Functional Conf about performance optimizations he made to make this library blazingly fast. So I would give it a try!
More on reddit.comVideos
When starting a new project, should I try to use only Text?
i.e. do not use String