简体   繁体   English

任何人都可以在haskell的以下代码中向我解释read函数的含义

[英]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 . 因此,基于签名,我们可以说,如果类型aRead 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] . StringChar列表 ,或更正式的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: 但是实际上,只有当ab均为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. 我们可以使用divmod来计算数字。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM