为了直截了当地查明问题,您不知道如何单独访问数字,因为您不了解 Haskell 类型和模式匹配。让我尝试帮助消除您的一些误解。
让我们看看你的清单:
[123, 123]
它的类型是什么?这显然是一个整数列表,或[Int]。使用列表,您可以在构造函数: 上模式匹配,lispers 将其称为“cons”或“列表构造函数”。您在: 的左侧放置了一个元素,在右侧放置了另一个列表。右边的列表可以是空列表[],基本表示列表结束。 Haskell 提供了“语法糖”以使列表更易于编写,但 [123,456] 实际上被脱糖为 123:(456:[])。因此,当您对(x:y:z) 进行模式匹配时,您现在可以看到x 将被分配123,y 将被分配456。 z 将是x 和y 之后的列表的其余部分;在这种情况下,只剩下[]。
那么,与: 匹配的模式适用于列表。 Ints 不是列表,因此您不能使用 : 对 Int 的数字进行模式匹配。但是,Strings 是列表,因为String 与[Char] 相同。因此,如果您将 Int 转换为 String,那么您可以在每个字符上进行模式匹配。
map show [123, 123]
map 将函数应用于列表的所有元素。 show 可以将Int 转换为String。所以我们在Ints 的列表上map show 得到Strings 的列表。
["123", "123"]
现在让我们将这些Strings 转换为Ints 的列表。由于String 只是[Char],我们将再次使用map。
map digitToInt "123" -- this requires that you import Data.Char (digitToInt)
这会给我们[1,2,3];列表中的每个Char 都会变成Int。这就是我们想要对列表["123", "123"] 中的每个String 执行的操作。我们想map digitToInt 到每个字符串。但是我们有一个Strings 的列表。那么我们该怎么办?我们映射它!
map (map digitToInt) ["123", "123"]
这会给我们[[1,2,3], [1,2,3]]。几乎是我们想要的。现在我们只需要将Ints ([[Int]]) 的列表扁平化为Int ([Int]) 的列表。我们怎么能做到这一点?停止......胡歌时间! Hoogling [[a]] -> [a] 我们发现第一个命中 concat 正是我们想要的。
让我们把它们放在一起。首先我们使用map show 来从[Int] 到[String]。然后我们执行map (map digitToInt) 以从[String] 到[[Int]]。然后我们执行concat 以从[[Int]] 到[Int]。那我们就直接print吧!
import Data.Char (digitToInt)
main = print $ concat $ map (map digitToInt) $ map show $ [123, 123]
现在让我们将大部分内容提取到函数 fat
import Data.Char (digitToInt)
main = print $ fat [123, 123]
fat :: [Int] -> [Int]
fat xs = concat $ map (map digitToInt) $ map show $ xs
从这里您可以通过几种不同的方式使其更漂亮。 concat $ map 与concatMap 相同,由于我们按顺序映射(map digitToInt) 和show,我们可以合并它们。同样让它变得无意义,我们可以得到一个相当简洁的定义:
fat = concatMap (map digitToInt . show)