[英]haskell [[Char]] to [[Int]]
I've got problem with a Haskell program. 我遇到了Haskell程序的问题。 I'm trying to change [[Char]]
to [[Int]]
I've got 我正试图改变[[Char]]
到[[Int]]
我有
["2","2","1","2,2","1"]
list of char list and I'm trying to change it to [[Int]]
char列表列表,我正在尝试将其更改为[[Int]]
[[2],[2],[1],[2,2],[1]]
I've tried 我试过了
f :: [String] -> [Int]
f = map read
but it gives me 但它给了我
[2,2,1,*** Exception: Prelude.read: no parse [2,2,1,***例外:Prelude.read:没有解析
Can anybody help me with this? 任何人都可以帮我吗?
The reason that this fails is because a string "2,2"
can not be converted to an Int
itself: this is a digit followed by a comma, followed by a digit. 这种失败的原因是因为字符串"2,2"
无法转换为Int
本身:这是一个数字,后跟一个逗号,后跟一个数字。 An Int
is parsed by an optional minus sign, followed by some digits, and some extra possibilities like hexadecimal numbers, but let us ignore these for now. Int
由可选的减号解析,后跟一些数字,以及一些额外的可能性,如十六进制数,但让我们暂时忽略它们。
The type signature you specify for f
is however incorrect, based on the expected output. 但是,根据预期的输出,为f
指定的类型签名是不正确的。 Your output type seems to be a list of lists of Int
s, so [[Int]]
. 您的输出类型似乎是Int
的列表列表 ,因此[[Int]]
。 That means that you should specify f
as: 这意味着您应该将f
指定为:
f :: [String] -> [[Int]]
f = ...
We thus need to read every String
to an [Int]
. 因此,我们需要将每个String
读取到[Int]
。 We can not use read
directly here, since read
ing to an [Int]
expects the string to start and end with square brackets . 我们不能直接在这里使用read
,因为read
[Int]
期望字符串以方括号开头和结尾。 We can however add these manually like: 然而,我们可以手动添加这些:
f :: [String] -> [[Int]]
f = map (\s -> read ('[' : s ++ "]"))
or a point-free version: 或无点版本:
f :: [String] -> [[Int]]
f = map (read . ('[' :) . (++ "]"))
For example: 例如:
Prelude> f ["2","2","1","2,2","1"]
[[2],[2],[1],[2,2],[1]]
readMaybe
使用readMaybe
实现更安全的解析 Parsing from String
s like in the above way is of course not very " safe ", since it is possible that the String
does not follow the format. 像上面那样从String
解析当然不是很“ 安全 ”,因为String
可能不遵循格式。 We can make this more safe and use for example readMaybe :: Read a => String -> Maybe a
: 我们可以使这更安全,并使用例如readMaybe :: Read a => String -> Maybe a
:
import Text.Read(readMaybe)
f :: [String] -> [Maybe [Int]]
f = map (readMaybe . ('[' :) . (++ "]"))
For example: 例如:
Prelude Text.Read> f ["2", "3;2", "4,7,3", "bla"]
[Just [2],Nothing,Just [4,7,3],Nothing]
we can omit the failed reads for example by using catMaybes :: [Maybe a] -> [a]
: 我们可以省略失败的读取,例如使用catMaybes :: [Maybe a] -> [a]
:
import Data.Maybe(catMaybes)
import Text.Read(readMaybe)
f :: [String] -> [[Int]]
f = catMaybes . map (readMaybe . ('[' :) . (++ "]"))
For example: 例如:
Prelude Data.Maybe Text.Read> f ["2", "3;2", "4,7,3", "bla"]
[[2],[4,7,3]]
or as @dfeuer said, we can use traverse :: (Applicative f, Traversable t) => (a -> fb) -> ta -> f (tb)
to return an [[Int]]
result wrapped in a Just
if all parsing succeeded, and Nothing
otherwise: 或者如@dfeuer所说,我们可以使用traverse :: (Applicative f, Traversable t) => (a -> fb) -> ta -> f (tb)
返回包含在Just
的[[Int]]
结果所有解析都成功了,否则Nothing
:
import Text.Read(readMaybe)
f :: [String] -> Maybe [[Int]]
f = traverse (readMaybe . ('[' :) . (++ "]"))
For example: 例如:
Prelude Text.Read> f ["2","2","1","2,2","1"]
Just [[2],[2],[1],[2,2],[1]]
Prelude Text.Read> f ["2", "3;2", "4,7,3", "bla"]
Nothing
readEither
使用readEither
解析错误消息 We can obtain an error message wrapped in a Left
in case the parsing fails by using readEither :: Read a => String -> Either String a
: 我们可以通过使用readEither :: Read a => String -> Either String a
获取解析失败的情况下包含在Left
中的错误消息:
import Text.Read(readEither)
f :: [String] -> [Either String [Int]]
f = map (readEither . ('[' :) . (++ "]"))
For example: 例如:
Prelude Text.Read> f ["2", "3;2", "4,7,3", "bla"]
[Right [2],Left "Prelude.read: no parse",Right [4,7,3],Left "Prelude.read: no parse"]
and use traverse
in the same way to obtain an error message wrapped in a Left
or the complete result in a Right
: 并以相同的方式使用traverse
来获取包含在Left
的错误消息或Right
的完整结果:
import Text.Read(readEither)
f :: [String] -> Either String [[Int]]
f = traverse (readEither . ('[' :) . (++ "]"))
For example: 例如:
Prelude Text.Read> f ["2","2","1","2,2","1"]
Right [[2],[2],[1],[2,2],[1]]
Prelude Text.Read> f ["2", "3;2", "4,7,3", "bla"]
Left "Prelude.read: no parse"
Here, like @dfeuer says, it does not really shows much information. 在这里,就像@dfeuer所说,它并没有真正显示太多信息。 There are however parsers that can provide more informative parsing errors. 但是,解析器可以提供更多信息性的解析错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.