As an exercise I wrote a short Haskell function that returns the first four characters of a string, concatenated. I had great trouble converting the chars to strings and resorted to an ugly replicate
hack. What's the best way to improve this function? (I'm guessing that both the pattern and the output can be improved.)
concatFirstFour :: [Char] -> [Char]
concatFirstFour (a:b:c:d:_) = (replicate 1 a) ++ (replicate 1 b) ++ (replicate 1 c) ++ (replicate 1 d)
concatFirstFour xs = error "Need at least four characters."
Update: Thank you so much, everyone. I learned several things from all the answers and comments. I understand types much better.
Here's the code I ended up using:
initFirstFour :: [a] -> [a]
initFirstFour str
| length str > 3 = take 4 str
| otherwise = error "Need at least four characters."
Update 2: Changed the second pattern from xs to _ per ptival's comment. Lazy eval FTW.
Update 3: Cleaner guards from tew88's comment.
concatFirstFour (a:b:c:d:_) = [a,b,c,d]
concatFirstFour _ = error "Need at least four characters."
or
concatFirstFour = take 4
but this last one doesn't fail on short lists...
Also note you don't need to specify the type is a [Char] (or String), since you never use this assumption in the code. Let it be [a] -> [a].
Strings are just lists of characters, so you don't need to convert characters to string and then concatenate the strings. There are a few different ways to do this.
First off, if you want a list with just one element, you can use [x]
. So:
concatFirstFour (a:b:c:d:_) = [a] ++ [b] ++ [c] ++ [d]
But this isn't really necessary. You could just do this:
concatFirstFour (a:b:c:d:_) = [a, b, c, d]
Or this:
concatFirstFour (a:b:c:d:_) = a:b:c:d:[]
Or, my preferred way:
concatFirstFour str = take 4 str
Since str
is just a list, you can take
the first four characters to get a new "string."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With