How to split a string in Haskell?
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.
Related videos on Youtube
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, 2021Comments
-
Eric Wilson over 2 years
Is there a standard way to split a string in Haskell?
lines
andwords
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 about 13 yearsI would really like to such a function in a future release of
Data.List
or evenPrelude
. It's so common and nasty if not available for code-golf.
-
-
gawi about 13 yearsCool. 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 almost 12 yearsI was looking for a built-in
split
, being spoiled by languages with well-developed libraries. But thanks anyway. -
Tony Morris over 11 yearsYou 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 over 11 yearsotherwise if external packages are acceptable, MissingH also provides a split function: hackage.haskell.org/packages/archive/MissingH/1.2.0.0/doc/html/… That package also provides plenty of other "nice-to-have" functions and I find that quite some packages depend on it.
-
The Internet over 10 yearsThe split package is now apart of the haskell platform as of most recent release.
-
Anderson Green over 10 years@dave How can I import and use the split package, then?
-
The Internet over 10 yearsimport Data.List.Split (splitOn) and go to town. splitOn :: Eq a => [a] -> [a] -> [[a]]
-
ChrisF almost 8 yearsThe link is dead, I tried updating it to what it reported the link should be but still returned the same page.
-
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 about 6 yearsPlease, don’t use regular expressions to split strings. Thank you.
-
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 thebuild-depends
list in your cabal file, e.g. if your project is called hello, then in thehello.cabal
file below theexecutable hello
line put a line like ` build-depends: base, split` (note two space indent). Then build using thecabal build
command. Cf. haskell.org/cabal/users-guide/… -
Enlico about 4 years@kirelagin, why this comment? I'm learning Haskell, and I'd like to know the rational behind your comment.
-
Enlico about 4 years@Andrey, is there a reason why I cannot even run the first line in my
ghci
? -
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 over 3 years
Could not find module ‘Text.Regex’ Perhaps you meant Text.Read (from base-4.10.1.0)
-
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 over 3 yearsCouldn't match type ‘T.Text’ with ‘Char’ Expected type: [Char] Actual type: [T.Text]
-
Microtribute over 2 yearsOh 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 over 2 yearsYou 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 over 2 yearsThat 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 over 2 years@Yuri Kovalenko
words
does; trywords [if c == ',' then ' ' else c|c <- "my, comma, separated, list "]
-
Microtribute over 2 yearsHaskell 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 thesplit
package will also include a bunch of redundant functions. You only asked for asplit
function, and I gave exactly that to you and NO MORE. -
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.