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