In Haskell, how do you trim whitespace from the beginning and end of a string?

37,996

Solution 1

If you have serious text processing needs then use the text package from hackage:

> :set -XOverloadedStrings
> import Data.Text
> strip "  abc   "
"abc"

If you're too stubborn to use text and don't like the inefficiency of the reverse method then perhaps (and I mean MAYBE) something like the below will be more efficient:

import Data.Char

trim xs = dropSpaceTail "" $ dropWhile isSpace xs

dropSpaceTail maybeStuff "" = ""
dropSpaceTail maybeStuff (x:xs)
        | isSpace x = dropSpaceTail (x:maybeStuff) xs
        | null maybeStuff = x : dropSpaceTail "" xs
        | otherwise       = reverse maybeStuff ++ x : dropSpaceTail "" xs


> trim "  hello this \t should trim ok.. .I  think  ..  \t "
"hello this \t should trim ok.. .I  think  .."

I wrote this on the assumption that the length of spaces would be minimal, so your O(n) of ++ and reverse is of little concern. But once again I feel the need to say that if you actually are concerned about the performance then you shouldn't be using String at all - move to Text.

EDIT making my point, a quick Criterion benchmark tells me that (for a particularly long string of words with spaces and ~200 pre and post spaces) my trim takes 1.6 ms, the trim using reverse takes 3.5ms, and Data.Text.strip takes 0.0016 ms...

Solution 2

From: http://en.wikipedia.org/wiki/Trim_(programming)#Haskell

import Data.Char (isSpace)

trim :: String -> String
trim = f . f
   where f = reverse . dropWhile isSpace

Solution 3

After this question was asked (circa 2012) Data.List got dropWhileEnd making this a lot easier:

trim = dropWhileEnd isSpace . dropWhile isSpace

Solution 4

Inefficient but easy to understand and paste in where needed:

strip = lstrip . rstrip
lstrip = dropWhile (`elem` " \t")
rstrip = reverse . lstrip . reverse

Solution 5

Nowadays the MissingH package ships with a strip function:

import           Data.String.Utils

myString = "    foo bar    "
-- strip :: String -> String
myTrimmedString = strip myString
-- myTrimmedString == "foo bar"

So if the conversion from String to Text and back does not make sense in your situation, you could use the function above.

Share:
37,996
Eric Normand
Author by

Eric Normand

Updated on July 05, 2022

Comments

  • Eric Normand
    Eric Normand almost 2 years

    How do you trim whitespace from the start and end of a string?

    trim "  abc " 
    
    =>
    
    "abc"
    

    Edit:

    Ok, let me be a little clearer. I did not understand that string literals were treated so differently from Strings.

    I would like to do this:

    import qualified Data.Text as T
    let s :: String = "  abc  "
    in T.strip s
    

    Is this possible in Haskell? I am using -XOverloadedStrings but that appears only to work for literals.