Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有人能解释一下haskell中下面代码中read函数的含义吗_Haskell - Fatal编程技术网

有人能解释一下haskell中下面代码中read函数的含义吗

有人能解释一下haskell中下面代码中read函数的含义吗,haskell,Haskell,我无法理解上面代码中read函数的含义 注意:此处所有的数字仅适用于正数(包括零),负数将出错 read有签名: toDigits n = map (\c -> read [c]) (show n) 因此,根据签名,我们可以说,如果一个类型a是reada,那么它将字符串转换为a。在自然语言中,它意味着它将一个对象的文本表示解析为该对象。例如,它可以将“\'foo\”解析为字符串“foo”。或者它可以将“23”解析为整数23。是输出类型决定了我们解析元素的内容,但基于函数,它可能有一些类型

我无法理解上面代码中read函数的含义

注意:此处所有的
数字
仅适用于正数(包括零),负数将出错

read
有签名:

toDigits n = map (\c -> read [c]) (show n)
因此,根据签名,我们可以说,如果一个类型
a
reada
,那么它将
字符串
转换为
a
。在自然语言中,它意味着它将一个对象的文本表示解析为该对象。例如,它可以将
“\'foo\”
解析为字符串
“foo”
。或者它可以将
“23”
解析为整数
23
。是输出类型决定了我们解析元素的内容,但基于函数,它可能有一些类型签名
toDigits::Int->Int

现在我们仍然需要了解函数是如何工作的<代码>显示::显示a=>a->String实际上是
read
的反面:它将对象转换为文本表示。例如,
23
被转换成
“23”
,一个
字符串

因此,首先我们将一个数字,例如
1425
转换为
“1425”
String
Char
s的列表,或者更正式的
type String=[Char]
。这意味着我们可以在它上面执行
map
,并且
map
将一次处理
字符串的每个
Char

现在,对于每个字符
c
,我们首先构造一个列表
[c]
。我们为什么要这样做?使其成为
字符串
。因为
字符串
是字符列表。具有一个字符的列表等于具有该字符的字符串。接下来,我们调用1字符字符串上的read,将其转换为我们喜欢的任何内容

这意味着
toDigits
具有最通用的类型:

read :: Read a => String -> a
请注意,根据此签名,我们不受
a
应该是数字这一事实的限制,也不受输出应该是数字这一事实的限制。只要
a
对象的文本表示可以拆分为1个字符的字符串,这些字符串可以单独解析为
b
对象,我们就可以了。然而,在现实中,只有当
a
b
都是
整数时,它才有意义,因此:

toDigits :: (Show a, Read b) => a -> [b]
最后一点需要注意的是,我们可以使实现更加优雅,如:

toDigits :: (Show a, Read b, Integral a, Integral b) => a -> [b]
我们可以进一步将输出类型限制为
Int
,因为
Int
保证所有数字都在(包括)0和9之间,并且构造:

toDigits :: (Show a, Read b, Integral a, Integral b) => a -> [b]
toDigits = map (read . pure) . show
也就是说,该函数做出了一些假设:例如,所有数字都有一个文本表示法,即十进制表示法。这本身并不能保证:我可以构建自己的数字系统,并决定构建一个使用一元系统(尽管这可能不是一个好主意)的节目。这使得它有点危险:你依赖于一些无法保证的假设。而且这个

我们可以使用
div
mod
来计算数字。例如:

import Data.Char(digitToInt)

toDigits :: (Show a, Integral a) => a -> [Int]
toDigits = map digitToInt . show
toDigits::积分a=>a->[a]
toDigits 0=[0]
toDigits n | n<0=错误“负数!”
|否则=步骤[]n
其中步骤xs 0=xs
步骤xs d=步骤(模块d 10):xs(分区d 10)
此外,我们删除了
Show
类型约束,因此没有此类
Show
的积分仍然可以处理

注意:此处所有的
数字
仅适用于正数(包括零),负数将出错

read
有签名:

toDigits n = map (\c -> read [c]) (show n)
因此,根据签名,我们可以说,如果一个类型
a
reada
,那么它将
字符串
转换为
a
。在自然语言中,它意味着它将一个对象的文本表示解析为该对象。例如,它可以将
“\'foo\”
解析为字符串
“foo”
。或者它可以将
“23”
解析为整数
23
。是输出类型决定了我们解析元素的内容,但基于函数,它可能有一些类型签名
toDigits::Int->Int

现在我们仍然需要了解函数是如何工作的<代码>显示::显示a=>a->String
实际上是
read
的反面:它将对象转换为文本表示。例如,
23
被转换成
“23”
,一个
字符串

因此,首先我们将一个数字,例如
1425
转换为
“1425”
String
Char
s的列表,或者更正式的
type String=[Char]
。这意味着我们可以在它上面执行
map
,并且
map
将一次处理
字符串的每个
Char

现在,对于每个字符
c
,我们首先构造一个列表
[c]
。我们为什么要这样做?使其成为
字符串
。因为
字符串
是字符列表。具有一个字符的列表等于具有该字符的字符串。接下来,我们调用1字符字符串上的read,将其转换为我们喜欢的任何内容

这意味着
toDigits
具有最通用的类型:

read :: Read a => String -> a
请注意,根据此签名,我们不受
a
应该是数字这一事实的限制,也不受输出应该是数字这一事实的限制。只要
a
对象的文本表示可以拆分为1个字符的字符串,这些字符串可以单独解析为
b
对象,我们就可以了。然而,在现实中,只有当
a
b
都是
整数时,它才有意义,因此:

toDigits :: (Show a, Read b) => a -> [b]
最后一点需要注意的是,我们可以使实现更加简单