如何在不格式化的情况下将数字列表转换为字符串
How to convert list of numbers to string without formatting
这是我目前拥有的:
toStr :: (Num a) => [a] -> String
toStr (x:xs)
| length xs == 0 = []
| length xs > 0 = show x : toStr xs
我一直收到这个错误:
* Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
我不明白为什么它接收的是 Char 而不是 [Char]。提前致谢。
求助,我想做的是将二进制列表 [1, 0, 0, 1, 1, 0] 转换为这样的列表“100110”。
如 Sergey 所述,不能使用“:”运算符,因为表达式 "show x" returns 是一个字符串而不是单个字符。
下面这段代码似乎可以满足您的要求:
toStr :: (Num a, Show a) => [a] -> String
toStr (x:xs)
| null xs = show x -- avoid using length because of cost
| not (null xs) = (show x) ++ (toStr xs)
toStr [] = ""
main = do
let ls1 = [ 13, 17, 19, 23 ]
let st1 = toStr ls1
let st2 = concatMap show ls1 -- as per melpomene's remark
putStrLn $ "st1 = " ++ st1
putStrLn $ "st2 = " ++ st2
附带说明一下,Haskell 程序员通常在只想知道列表是否为空时避免使用 length 函数。如果你这样做,事情会变得非常糟糕,因为我们可能有无限的惰性列表。
理解问题
toStr :: (Num a) => [a] -> String
toStr (x:xs)
| length xs == 0 = []
| length xs > 0 = show x : toStr xs
^ ^ ^
This is a String | |
| This is a String
This is a function of type String -> [String] -> [String]
所以你有:
show x
这是一个 String
toStr xs
这是一个 String
- 需要
String
和 [String]
的函数 :
。
关于 toStr xs
的分歧是一个字符串,但 :
预期它是一个字符串列表,这是问题的症结所在。您想将字符串连接成一个字符串 (show x ++ toStr xs
)。
了解下一个问题*
现在您应该还有其他一些问题。首先,您有一个 Num a => a
,您尝试 show
。函数 show
不是 Num
的一部分,而是 Show
class 的一部分,因此将 Num a =>
更改为 Show a =>
。
最后,这段代码不能很好地处理空列表的情况:
toStr (x:xs)
| length xs == 0 = []
注意到 x
之后没有任何内容,此代码将忽略最后一个值 x
和 return 空列表。它不处理没有 "last element" 并且您所拥有的只是空列表的情况。要处理这个问题,请尝试 toStr [] = []
.
放在一起
toStr :: (Show a) => [a] -> String
toStr [] = []
toStr (x:xs) = show x ++ toStr xs
结果为:
> toStr [1,0,0,1,1]
"10011"
惯用代码
以上是一个很好的结果,但是在编写 Haskell 时通常不需要手动原始递归函数。大多数操作都是对数据的 map
或 fold
类型。在这种情况下,它是 show
函数的映射(注意它是如何 show
ing 每个元素的)和 ++
函数的 fold
- 也称为字符串连接.
toStr2 xs = foldr (++) "" (map show xs)
-- > toStr2 [1,0,0,1,1]
-- "10011"
即使这样也可以进一步简化。如此普遍,存在一个特殊的功能 concatMap
:
toStr3 xs = concatMap show xs
我们可以"eta reduce"(删除函数的最外层参数definition/application - 考虑将一个函数定义为另一个函数而不是它产生的值):
toStr4 = concatMap show
或者,我们可以 re-gain fold 和 map 的原始 verb-age。 concatMap
函数只是 fold
+ map
的一种特定类型,适用于列表。有一个更通用的 foldMap
适用于任何产生幺半群的函数(列表就是这样一种结构,这意味着字符串也是,因为它们是字符列表):
toStr5 = foldMap show
这是我目前拥有的:
toStr :: (Num a) => [a] -> String
toStr (x:xs)
| length xs == 0 = []
| length xs > 0 = show x : toStr xs
我一直收到这个错误:
* Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
我不明白为什么它接收的是 Char 而不是 [Char]。提前致谢。
求助,我想做的是将二进制列表 [1, 0, 0, 1, 1, 0] 转换为这样的列表“100110”。
如 Sergey 所述,不能使用“:”运算符,因为表达式 "show x" returns 是一个字符串而不是单个字符。
下面这段代码似乎可以满足您的要求:
toStr :: (Num a, Show a) => [a] -> String
toStr (x:xs)
| null xs = show x -- avoid using length because of cost
| not (null xs) = (show x) ++ (toStr xs)
toStr [] = ""
main = do
let ls1 = [ 13, 17, 19, 23 ]
let st1 = toStr ls1
let st2 = concatMap show ls1 -- as per melpomene's remark
putStrLn $ "st1 = " ++ st1
putStrLn $ "st2 = " ++ st2
附带说明一下,Haskell 程序员通常在只想知道列表是否为空时避免使用 length 函数。如果你这样做,事情会变得非常糟糕,因为我们可能有无限的惰性列表。
理解问题
toStr :: (Num a) => [a] -> String
toStr (x:xs)
| length xs == 0 = []
| length xs > 0 = show x : toStr xs
^ ^ ^
This is a String | |
| This is a String
This is a function of type String -> [String] -> [String]
所以你有:
show x
这是一个String
toStr xs
这是一个String
- 需要
String
和[String]
的函数:
。
关于 toStr xs
的分歧是一个字符串,但 :
预期它是一个字符串列表,这是问题的症结所在。您想将字符串连接成一个字符串 (show x ++ toStr xs
)。
了解下一个问题*
现在您应该还有其他一些问题。首先,您有一个 Num a => a
,您尝试 show
。函数 show
不是 Num
的一部分,而是 Show
class 的一部分,因此将 Num a =>
更改为 Show a =>
。
最后,这段代码不能很好地处理空列表的情况:
toStr (x:xs)
| length xs == 0 = []
注意到 x
之后没有任何内容,此代码将忽略最后一个值 x
和 return 空列表。它不处理没有 "last element" 并且您所拥有的只是空列表的情况。要处理这个问题,请尝试 toStr [] = []
.
放在一起
toStr :: (Show a) => [a] -> String
toStr [] = []
toStr (x:xs) = show x ++ toStr xs
结果为:
> toStr [1,0,0,1,1]
"10011"
惯用代码
以上是一个很好的结果,但是在编写 Haskell 时通常不需要手动原始递归函数。大多数操作都是对数据的 map
或 fold
类型。在这种情况下,它是 show
函数的映射(注意它是如何 show
ing 每个元素的)和 ++
函数的 fold
- 也称为字符串连接.
toStr2 xs = foldr (++) "" (map show xs)
-- > toStr2 [1,0,0,1,1]
-- "10011"
即使这样也可以进一步简化。如此普遍,存在一个特殊的功能 concatMap
:
toStr3 xs = concatMap show xs
我们可以"eta reduce"(删除函数的最外层参数definition/application - 考虑将一个函数定义为另一个函数而不是它产生的值):
toStr4 = concatMap show
或者,我们可以 re-gain fold 和 map 的原始 verb-age。 concatMap
函数只是 fold
+ map
的一种特定类型,适用于列表。有一个更通用的 foldMap
适用于任何产生幺半群的函数(列表就是这样一种结构,这意味着字符串也是,因为它们是字符列表):
toStr5 = foldMap show