[英]Can anyone explain me the meaning of read function in the following code in haskell
toDigits n = map (\c -> read [c]) (show n)
我无法理解上述代码中的读取功能的含义
Note : all
toDigits
here only work with positive numbers (zero included), and will error on negative numbers.注意 :此处所有
toDigits
仅适用于正数(包括零),并且对负数会出错。
read
has signature: read
有签名:
read :: Read a => String -> a
So based on the signature we can say that if a type a
is Read a
, then it turns a String
into that a
. 因此,基于签名,我们可以说,如果类型
a
为Read a
,则它将String
转换为那个a
。 In natural language it means that it parses a textual representation of an object into that object. 用自然语言表示这意味着它将对象的文本表示形式解析为该对象。 For instance it can parse
"\\"foo\\""
into the String "foo"
. 例如,它可以将
"\\"foo\\""
解析为字符串"foo"
。 Or it can parse "23"
into the integer 23
. 或者它可以将
"23"
解析为整数23
。 It is the output type that determines into what we parse the elements, but based on the function, it has probably some type signature toDigits :: Int -> Int
. 输出类型决定了我们解析元素的方式,但是基于函数,它可能具有
toDigits :: Int -> Int
类型签名。
Nowe we still have to understand how the function works. 现在,我们仍然必须了解该功能的工作原理。
show :: Show a => a -> String
is actually the opposite of read
: it converts an object into a textual representation. show :: Show a => a -> String
实际上与read
相反:它将对象转换为文本表示形式。 So 23
is for instance converted into "23"
, a String
. 所以
23
是例如转换成"23"
,一个String
。
So first we convert a number, for instance 1425
into "1425"
. 所以首先我们将一个数字,例如
1425
转换为"1425"
。 A String
is a list of Char
s, or more formal type String = [Char]
. String
是Char
的列表 ,或更正式的type String = [Char]
。 So that means we can perform a map
on it, and map
will thus process each Char
of the String
, one at a time. 因此,这意味着我们可以在其上执行
map
,并且map
将因此一次处理String
每个Char
。
Now for each char c
, we first construct a list [c]
. 现在,对于每个字符
c
,我们首先构造一个列表[c]
。 Why do we do that? 我们为什么要这样做? To make it a
String
. 使它成为
String
。 Since a String
is a list of chars. 由于
String
是字符列表。 A list with one character is equal to a string with that character. 具有一个字符的列表等于具有该字符的字符串。 Next we call read on the 1-char String, to turn it into whatever we like.
接下来,我们对1-char字符串调用read,将其转换为我们喜欢的任何形式。
This means that toDigits
has as most generic type: 这意味着
toDigits
具有最通用的类型:
toDigits :: (Show a, Read b) => a -> [b]
Note that according to this signature, we are not bounded by the fact that a
should be a number, nor that the output should be numbers. 请注意,根据该签名,我们不受以下事实的束缚:
a
应该是数字,输出也不应该是数字。 As long as the textual representation of the a
object can be split into 1-char strings that can be parsed indivudually into object of b
, we are fine. 只要
a
对象的文本表示形式可以拆分为1个字符的字符串,并且可以将其单独解析为b
对象,我们就可以了。 However in reality, it will probably only make sense if both a
and b
are Integral
, so: 但是实际上,只有当
a
和b
均为Integral
时才有意义。
toDigits :: (Show a, Read b, Integral a, Integral b) => a -> [b]
A final note is that we can make the implementation a bit more elegant, like: 最后一点是,我们可以使实现更加优雅,例如:
toDigits :: (Show a, Read b, Integral a, Integral b) => a -> [b]
toDigits = map (read . pure) . show
We can further restrict the output type to Int
, since an Int
is guaranteed to have all numbers between (and including) 0 and 9, and construct: 我们可以进一步将输出类型限制为
Int
,因为可以保证一个Int
所有数字都在0到9之间(包括0和9),并构造:
import Data.Char(digitToInt)
toDigits :: (Show a, Integral a) => a -> [Int]
toDigits = map digitToInt . show
That being said, the function makes some assumptions: for instance that all numbers will have a textual representation that is the decimal notation. 话虽这么说,该函数做出了一些假设:例如,所有数字都将具有文本表示形式,即十进制表示法。 This is not per se guaranteed: I could construct my own number system, and decide to construct a show that for instance uses the unary system (although that is probably not a good idea).
这本身并不能保证:我可以构建自己的数字系统,并决定构建一个节目,例如使用一元制(尽管这可能不是一个好主意)。 This makes it a bit a dangerous approach: you rely on some assumptions that are not guaranteed.
这使其成为一种危险的方法:您依赖某些无法保证的假设。 Furthermore this
再说这个
We can use the div
and mod
to calculate the digits. 我们可以使用
div
和mod
来计算数字。 For instance like: 例如:
toDigits :: Integral a => a -> [a]
toDigits 0 = [0]
toDigits n | n < 0 = error "Negative number!"
| otherwise = step [] n
where step xs 0 = xs
step xs d = step ((mod d 10):xs) (div d 10)
furthermore we dropped the Show a
type constraint, so integrals that do not have such show
can still be handled. 此外,我们删除了
Show a
type约束,因此仍可以处理不具有此类show
积分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.