Reputation: 503
I've got a list of strings, is it possible to convert it to an list of ints?
E.g.:
["1","2"] -> [1,2]
Upvotes: 21
Views: 35068
Reputation: 6760
This fails:
map read ["1","2"]
[*Exception: Prelude.read: no parse
The way to do it is :
map (read::String->Int) ["1","2"]
[1,2]
:: [Int]
Outside of GHCI, in a .hs file it would be:
let intList = map (read::String->Int) ["1","2"]
Upvotes: 40
Reputation: 120751
The general answer to such questions is to split the task up into parts: [String] -> [Int]
looks like a combination of String -> Int
and [a] -> [b]
. Hoogle (linked) will give you some results to both, let's see...
$ hoogle 'String -> Int'
Test.HUnit.Base Label :: String -> Node
Prelude error :: [Char] -> a
Prelude length :: [a] -> Int
Data.List length :: [a] -> Int
Data.Char digitToInt :: Char -> Int
Data.Char ord :: Char -> Int
Debug.Trace trace :: String -> a -> a
Network.BufferType buf_fromStr :: BufferOp a -> String -> a
Network.Socket send :: Socket -> String -> IO Int
Graphics.UI.GLUT.Callbacks.Window Char :: Char -> Key
Prelude read :: Read a => String -> a
Text.Read read :: Read a => String -> a
Data.String fromString :: IsString a => String -> a
GHC.Exts fromString :: IsString a => String -> a
Control.Monad.Trans.Error strMsg :: Error a => String -> a
Control.Monad.Error.Class strMsg :: Error a => String -> a
...
Ugh, a lot of rubbish. We can first eliminate those from packages you have nothing to do with...
Prelude error :: [Char] -> a
Prelude length :: [a] -> Int
Data.List length :: [a] -> Int
Data.Char digitToInt :: Char -> Int
Data.Char ord :: Char -> Int
Prelude read :: Read a => String -> a
Text.Read read :: Read a => String -> a
Data.String fromString :: IsString a => String -> a
Text.Printf printf :: PrintfType r => String -> r
error
sounds hardly like what you want. length
neither. digitToInt
? Sounds kind of right – and works in fact, but just with single-digit numbers. read
? Perhaps not the name you would have expected, but if you think about it this is the right thing: converting a string to something more meaningful (like a number) is like reading some text.
Right, on the other side Hoogle gives us the thing we want right up front:
$ hoogle '[a] -> [b]'
Prelude map :: (a -> b) -> [a] -> [b]
Data.List map :: (a -> b) -> [a] -> [b]
Prelude concatMap :: (a -> [b]) -> [a] -> [b]
Data.List concatMap :: (a -> [b]) -> [a] -> [b]
Data.Maybe mapMaybe :: (a -> Maybe b) -> [a] -> [b]
Prelude cycle :: [a] -> [a]
Data.List cycle :: [a] -> [a]
Prelude init :: [a] -> [a]
Data.List init :: [a] -> [a]
Prelude reverse :: [a] -> [a]
As you see most of these functions are called something with "map", which might again not be the name you expected – but apparently that's what this operation is called! The one you're looking for is quite the simplest.
Finally, we need to combine those two functions. map
needs another function as its first argument – well, that's obviously read
then! So you simply apply map
to read
. The next argument is the list of [a]
s: aha, we're done already!
You can check this by launching up ghci:
Prelude> :t map read
map read :: Read b => [String] -> [b]
There's still this b
in here instead of Int
, but never mind that: b
can be any type you want! – provided it has a Read
instance. Int
has:
Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in `GHC.Types'
instance Bounded Int -- Defined in `GHC.Enum'
instance Enum Int -- Defined in `GHC.Enum'
instance Eq Int -- Defined in `GHC.Classes'
instance Integral Int -- Defined in `GHC.Real'
instance Num Int -- Defined in `GHC.Num'
instance Ord Int -- Defined in `GHC.Classes'
instance Read Int -- Defined in `GHC.Read'
instance Real Int -- Defined in `GHC.Real'
instance Show Int -- Defined in `GHC.Show'
Upvotes: 5