list - haskell [[Char]] 到 [[Int]]

标签 list haskell char int

我的 Haskell 程序有问题。
我正在尝试更改 [[Char]][[Int]]我有

["2","2","1","2,2","1"] 

字符列表列表
我正在尝试将其更改为 [[Int]]
[[2],[2],[1],[2,2],[1]]

我试过了
f :: [String] -> [Int]
f = map read

但它给了我

[2,2,1,*** Exception: Prelude.read: no parse



有人可以帮我解决这个问题吗?

最佳答案

失败的原因是因为字符串 "2,2"无法转换为 Int本身:这是一个数字后跟一个逗号,后跟一个数字。安 Int由一个可选的减号解析,后跟一些数字,以及一些额外的可能性,如十六进制数字,但让我们暂时忽略这些。

您为 f 指定的类型签名然而,根据预期的输出,这是不正确的。您的输出类型似乎是 Int 的列表列表s,所以[[Int]] .这意味着您应该指定 f作为:

f :: [String] -> [[Int]]
f = ...

因此,我们需要阅读每个 String[Int] .我们不能使用 read直接在这里,因为 read联系 [Int]期望字符串以方括号开始和结束。但是,我们可以手动添加这些,例如:
f :: [String] -> [[Int]]
f = map (\s -> read ('[' : s ++ "]"))

或免积分版本:
f :: [String] -> [[Int]]
f = map (read . ('[' :) . (++ "]"))

例如:
Prelude> f ["2","2","1","2,2","1"] 
[[2],[2],[1],[2,2],[1]]

使用 readMaybe 实现更安全的解析

解析自 String像上面的方式当然不是很“安全”,因为有可能是 String不遵循格式。我们可以使它更安全和使用,例如 readMaybe :: Read a => String -> Maybe a :
import Text.Read(readMaybe)

f :: [String] -> [Maybe [Int]]
f = map (readMaybe . ('[' :) . (++ "]"))

例如:
Prelude Text.Read> f ["2", "3;2", "4,7,3", "bla"]
[Just [2],Nothing,Just [4,7,3],Nothing]

我们可以省略失败的读取,例如使用 catMaybes :: [Maybe a] -> [a] :
import Data.Maybe(catMaybes)
import Text.Read(readMaybe)

f :: [String] -> [[Int]]
f = catMaybes . map (readMaybe . ('[' :) . (++ "]"))

例如:
Prelude Data.Maybe Text.Read> f ["2", "3;2", "4,7,3", "bla"]
[[2],[4,7,3]]

或作为 @dfeuer说,我们可以使用 traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b) 返回 [[Int]]结果包裹在 Just 中如果所有解析都成功,则 Nothing除此以外:
import Text.Read(readMaybe)

f :: [String] -> Maybe [[Int]]
f = traverse (readMaybe . ('[' :) . (++ "]"))

例如:
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 解析错误消息

我们可以获得包裹在 Left 中的错误信息。如果使用 readEither :: Read a => String -> Either String a 解析失败:
import Text.Read(readEither)

f :: [String] -> [Either String [Int]]
f = map (readEither . ('[' :) . (++ "]"))

例如:
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"]

并使用 traverse以同样的方式获取包裹在 Left 中的错误信息或 Right 中的完整结果:
import Text.Read(readEither)

f :: [String] -> Either String [[Int]]
f = traverse (readEither . ('[' :) . (++ "]"))

例如:
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"

在这里,就像@dfeuer 所说的,它并没有真正显示太多信息。然而,有一些解析器可以提供更多信息丰富的解析错误。

关于list - haskell [[Char]] 到 [[Int]],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56116208/

相关文章:

list - Data.List.Split 的 `chunksOf` 值为 0

haskell - 管道教程 : ListT example

java - 将字符串列表传递给 Java 方法

C++:初始化列表/命名约定

java - 如何合并两个具有相同键的嵌套映射并保留值

haskell - GHC 构建标志的全局配置

Haskell:如何使用单子(monad)上下文编写带有参数的单子(monad)可变参数函数

c - 如何将变量放入 const char *array 并使大小成为变量

java - 不返回预期的连接字符串

c - 将连续符号替换为另一个符号