How to split a string in Haskell?

163,555

Solution 1

There is a package for this called split.

cabal install split

Use it like this:

ghci> import Data.List.Split
ghci> splitOn "," "my,comma,separated,list"
["my","comma","separated","list"]

It comes with a lot of other functions for splitting on matching delimiters or having several delimiters.

Solution 2

Remember that you can look up the definition of Prelude functions!

http://www.haskell.org/onlinereport/standard-prelude.html

Looking there, the definition of words is,

words   :: String -> [String]
words s =  case dropWhile Char.isSpace s of
                      "" -> []
                      s' -> w : words s''
                            where (w, s'') = break Char.isSpace s'

So, change it for a function that takes a predicate:

wordsWhen     :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'

Then call it with whatever predicate you want!

main = print $ wordsWhen (==',') "break,this,string,at,commas"

Solution 3

If you use Data.Text, there is splitOn:

http://hackage.haskell.org/packages/archive/text/0.11.2.0/doc/html/Data-Text.html#v:splitOn

This is built in the Haskell Platform.

So for instance:

import qualified Data.Text as T
main = print $ T.splitOn (T.pack " ") (T.pack "this is a test")

or:

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Text as T
main = print $ T.splitOn " " "this is a test"

Solution 4

Use Data.List.Split, which uses split:

[me@localhost]$ ghci
Prelude> import Data.List.Split
Prelude Data.List.Split> let l = splitOn "," "1,2,3,4"
Prelude Data.List.Split> :t l
l :: [[Char]]
Prelude Data.List.Split> l
["1","2","3","4"]
Prelude Data.List.Split> let { convert :: [String] -> [Integer]; convert = map read }
Prelude Data.List.Split> let l2 = convert l
Prelude Data.List.Split> :t l2
l2 :: [Integer]
Prelude Data.List.Split> l2
[1,2,3,4]

Solution 5

In the module Text.Regex (part of the Haskell Platform), there is a function:

splitRegex :: Regex -> String -> [String]

which splits a string based on a regular expression. The API can be found at Hackage.

Share:
163,555

Related videos on Youtube

Eric Wilson
Author by

Eric Wilson

Software developer, experienced in Java and Python in Linux environments, formerly a professor of mathematics. I'm a father of five children, and a husband of one wife.

Updated on July 10, 2021

Comments

  • Eric Wilson
    Eric Wilson over 2 years

    Is there a standard way to split a string in Haskell?

    lines and words work great from splitting on a space or newline, but surely there is a standard way to split on a comma?

    I couldn't find it on Hoogle.

    To be specific, I'm looking for something where split "," "my,comma,separated,list" returns ["my","comma","separated","list"].

    • fuz
      fuz about 13 years
      I would really like to such a function in a future release of Data.List or even Prelude. It's so common and nasty if not available for code-golf.
  • gawi
    gawi about 13 years
    Cool. I wasn't aware of this package. This is the ultimate split package as it gives much control over the operation (trim space in results, leave separators in result, remove consecutive separators, etc...). There are so many ways of splitting lists, it is not possible to have in single split function that will answer every needs, you really need that kind of package.
  • Eric Wilson
    Eric Wilson almost 12 years
    I was looking for a built-in split, being spoiled by languages with well-developed libraries. But thanks anyway.
  • Tony Morris
    Tony Morris over 11 years
    You wrote this in June, so I assume you've moved on in your journey :) As an exercise, trying rewriting this function without reverse or length as use of these functions incur an algorithmic complexity penalty and also prevent application to an infinite list. Have fun!
  • Emmanuel Touzery
    Emmanuel Touzery over 11 years
    otherwise if external packages are acceptable, MissingH also provides a split function: hackage.haskell.org/packages/archive/MissingH/1.2.0.0/doc/ht‌​ml/… That package also provides plenty of other "nice-to-have" functions and I find that quite some packages depend on it.
  • The Internet
    The Internet over 10 years
    The split package is now apart of the haskell platform as of most recent release.
  • Anderson Green
    Anderson Green over 10 years
    @dave How can I import and use the split package, then?
  • The Internet
    The Internet over 10 years
    import Data.List.Split (splitOn) and go to town. splitOn :: Eq a => [a] -> [a] -> [[a]]
  • ChrisF
    ChrisF almost 8 years
    The link is dead, I tried updating it to what it reported the link should be but still returned the same page.
  • Emmanuel Touzery
    Emmanuel Touzery over 7 years
    @RussAbbott probably you need to a dependency to the text package or install it. Would belong in another question though.
  • kirelagin
    kirelagin about 6 years
    Please, don’t use regular expressions to split strings. Thank you.
  • expz
    expz over 4 years
    @RussAbbott the split package is included in the Haskell Platform when you download it (haskell.org/platform/contents.html), but it is not automatically loaded when building your project. Add split to the build-depends list in your cabal file, e.g. if your project is called hello, then in the hello.cabal file below the executable hello line put a line like ` build-depends: base, split` (note two space indent). Then build using the cabal build command. Cf. haskell.org/cabal/users-guide/…
  • Enlico
    Enlico about 4 years
    @kirelagin, why this comment? I'm learning Haskell, and I'd like to know the rational behind your comment.
  • Enlico
    Enlico about 4 years
    @Andrey, is there a reason why I cannot even run the first line in my ghci?
  • kirelagin
    kirelagin about 4 years
    @EnricoMariaDeAngelis Regular expressions are a powerful tool for string matching. It makes sense to use them when you are matching something non-trivial. If you just want to split a string on something as trivial as another fixed string, there is absolutely no need to use regular expressions – it will only make the code more complex and, likely, slower.
  • Andrew Koster
    Andrew Koster over 3 years
    Could not find module ‘Text.Regex’ Perhaps you meant Text.Read (from base-4.10.1.0)
  • Andrew Koster
    Andrew Koster over 3 years
    "Please, don’t use regular expressions to split strings." WTF, why not??? Splitting a string with a regular expression is a perfectly reasonable thing to do. There are lots of trivial cases where a string needs to be split but the delimiter isn't always exactly the same.
  • Andrew Koster
    Andrew Koster over 3 years
    Couldn't match type ‘T.Text’ with ‘Char’ Expected type: [Char] Actual type: [T.Text]
  • Microtribute
    Microtribute over 2 years
    Oh come on... Ultimately what matters is not that something is liked by thousands of people. I am NOT forcing you to use it. It's ONLY there for those interested. Sounds like you're none of them.
  • Eric Wilson
    Eric Wilson over 2 years
    You say "liked by" -- I say "battle tested". It's fine if you enjoy sharing it. My question was for the standard way to do it, and that has been answersd.
  • Yuri Kovalenko
    Yuri Kovalenko over 2 years
    That does not distinguish between new added spaces and spaces that were here originally, so for "my,comma separated,list" it will see 4 parts instead of 3 as intended.
  • fp_mora
    fp_mora over 2 years
    @Yuri Kovalenko words does; try words [if c == ',' then ' ' else c|c <- "my, comma, separated, list "]
  • Microtribute
    Microtribute over 2 years
    Haskell does not come with the split function out of the box. Remember you asked a function that splits a string by a string (String -> String -> [String]), not by a char (Char->String->[String]). You have to install the split package, which is NOT a standard way EITHER. Installing the split package will also include a bunch of redundant functions. You only asked for a split function, and I gave exactly that to you and NO MORE.
  • Jörg Brüggmann
    Jörg Brüggmann almost 2 years
    ...simpler than what? Which kind of answers is your solution better of? Background: There is already some other answers.