0

How do I convert a list of integers [1,2,3] to a string "123"

Sorry for asking the obvious, but I don't seem to be able to find the answer elsewhere.

ruby_object
  • 1,229
  • 1
  • 12
  • 30
  • possible duplicate of [Convert list of Integers into one Int (like concat) in haskell](http://stackoverflow.com/questions/1918486/convert-list-of-integers-into-one-int-like-concat-in-haskell) – Knut Holm Feb 19 '15 at 16:35
  • 2
    it's not an obvious duplicate. I was after a string. – ruby_object Feb 19 '15 at 16:39
  • 2
    @Akarienta Not a duplicate, OP here wants to create a string, as stated explicitly in the question, while in the question you linked the goal was to create a new `Int` out of individual digits, the solutions are quite different (although both can be implemented with folds) – bheklilr Feb 19 '15 at 16:39
  • @bheklilr Well, so [this one](http://stackoverflow.com/questions/4324621/haskell-int-list-to-string) fore example. SO is full of these questions, author hasn't used searching. – Knut Holm Feb 19 '15 at 16:42
  • @Akarienta That's also not the same problem. I'm not doubting that this question has been asked before on SO, linking to somewhat similar but more complex problems is not going to help someone who is new to the language. If you can find an actual duplicate then I'll close it as such with my duphammer abilities, but I wouldn't consider either of those similar enough to mark this question as a dup. – bheklilr Feb 19 '15 at 16:51
  • @bheklilr Programmers have to think about the problems and be able to adapt very similar problem to his own. If he asks and gets the answer directly, he learns nothing and will be a beginner forever. – Knut Holm Feb 19 '15 at 17:02
  • 1
    @Akarienta This is true, but it doesn't help when someone simply doesn't know the functions to use yet. This could have been a two word solution of `concatMap show`, it's simply learning the API. The actual problem solved here was learning about previously unknown functions in Prelude. It's not that OP needed to adapt a more complex problem to fit his needs, it's merely ignorance of an existing solution. Yes, programmers need to learn how to read documentation and follow similar problems, but I'm going to wager that you didn't know about `concatMap` when you first started using Haskell. – bheklilr Feb 19 '15 at 17:09
  • @bheklilr Of course, I didn't. But had been searching and had found the solution. It was few years ago and I suppose that if it was possible then it is still possible today. I don't like to see somthing like "I don't seem to be able to find the answer elsewhere" if it is (obviously!) possible and quite easy to find. – Knut Holm Feb 19 '15 at 17:23

2 Answers2

10

The best way would be to use show and concatMap, which is just a combination of concat and map:

> concatMap show [1, 2, 3]
"123"

This also works for numbers with more than one digit:

> concatMap show [10, 20, 30]
"102030"

Since type String = [Char], we can just treat this as a list processing problem The first part is to convert each number to its String representation, which is done simply using show. Since we want to apply this to a list of numbers, map is the tool of choice. Finally, we want to join all the string representations (list of Char representations) into a single string (list of Char), so concat is appropriate:

> concat $ map show [1, 2, 3]
"123"

Whenever you see concat $ map f some_list, you can always use the pre-defined tool concatMap, since this is precisely its definition:

> concatMap show [1, 2, 3]
"123"

As pointed out in the comments, you can use foldMap from the Data.Foldable module that generalizes the whole "map then combine" functionality. The Foldable typeclass basically just means that you can use folds on it, and it also uses Monoid, which basically just means you have a way to combine two elements, such as concatenation for lists or addition for numbers. Alternatively, you can also use the fact that lists form a Monad and use the >>= operator as

> [1, 2, 3] >>= show
"123"

In the end, all of these operations pretty much boil down to applying a function to each element, then combining those results together using some other function. It's a very general pattern and can be applied in a lot of cases, hence why there's generalizations of it.

bheklilr
  • 53,530
  • 6
  • 107
  • 163
  • 2
    In the future, `foldMap show` could be the preferred way to say this. – Ingo Feb 19 '15 at 16:46
  • 1
    @Ingo We'll have to see how the FTP goes for the GHC 7.10 release first. Personally, I'm in favor of the burning bridges proposal, I think integrating Foldable and Traversable into Prelude would be great, but I do understand that it would make the initial learning curve a bit more difficult for Haskell. – bheklilr Feb 19 '15 at 17:04
  • 2
    It might be a good idea to mention that `(>>=) = flip foldMap` for the list Monad instance, so one can write `[1, 2, 3] >>= show`. – AJF Feb 19 '15 at 18:30
1

Alternatively, you could use

map (chr . (ord '0' +)) [1,2,3,4]

if all of your integers are single digits (you would need to import chr and ord from Data.Char).

This works because String is just a type synonym of [Char] in Haskell, so all we are doing is just mapping each Int in your list to the appropriate Char.

Emil
  • 2,098
  • 11
  • 25
  • 1
    Another way that avoids the import: `map ( (toEnum::Int->Char) . (fromEnum '0' +) ) [1,2,3,4]` – dfeuer Feb 19 '15 at 23:53