为何map read show无法拆分Integer转为String后的单个数值?
问题:将Integer拆分为[Integer]的字符串转换方法报错原因
我正在学习如何将一个多位数的Integer拆分为[Integer]类型。此前我看到过使用取模10运算符反复获取最后一位/余数,并将其添加到[Int]开头的实现方法,但我想知道为何不能先通过show函数将Integer转为String(即[Char]),再用map read处理每个Char以得到[Integer]?
我设想的代码如下:
deconstructor :: Integer -> [Integer] --(or trying [Char]) deconstructor n | n < 0 = map read (show (n * (-1))) | n == 0 = [read "0"] --(This line works) | otherwise = map read (show n) --(or in [] or with :: [Integer] on the end)
但总是出现类似如下错误:
* Couldn't match type `Char' with `[Char]' Expected: [String] Actual: String
单独执行show n可以正常编译并得到String/[Char],我理解map会对右侧数组的每个元素执行左侧操作(此处为read),但我哪里理解错了?是否需要先将String拆分为多个[String]?
解答
核心问题在于**read的类型**:read :: Read a => String -> a,它接收的是字符串([Char]),而不是单个Char。你用map read处理show n得到的String(也就是[Char])时,相当于把每个Char传给了read,但read不认单个字符,只认字符串,所以出现了类型不匹配的错误。
解决方法很简单:先把每个Char转换成单字符的String,再传给read。可以用函数组合实现这个逻辑,写法更简洁:
修正后的代码:
deconstructor :: Integer -> [Integer] deconstructor n | n < 0 = map (read . (:[])) (show (abs n)) | n == 0 = [0] -- 直接写[0]比read "0"更简洁高效 | otherwise = map (read . (:[])) (show n)
细节解释:
(:[])是Haskell里把单个元素转成单元素列表的写法,这里就是把单个Char变成String(因为String本质就是[Char])read . (:[])是函数组合,先执行(:[])把Char转成String,再执行read把这个单字符字符串解析成Integer- 用
abs n代替n * (-1)是Haskell处理绝对值的惯用写法,更易读
另外,你原来的[read "0"]完全可以直接写成[0],没必要通过read来转换,既简洁又高效。
内容的提问来源于stack exchange,提问作者Totally Legit
相关产品推荐
相关产品推荐

