您可能已经猜到了,完全是初学者。我已经完成了“Learn you a Haskell”,但我仍然在基础知识上挣扎。
我正在看这个线程 用 Haskell 将一个数字拆分成它的数字 ,这个函数开始变得有意义了
digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)
Run Code Online (Sandbox Code Playgroud)
丹尼尔问。
我知道 show 将我的输入数字作为字符串或字符列表返回,然后我可以使用 map 逐个修改元素。因此,每个“x”,作为一个字符,被匿名函数选择并读取为一个整数,新列表由 map 组成,包含所有读取的整数。那不read [x]应该read x吗?为什么列表中的每个读取 Char 都需要作为它自己的单例列表返回?在我看来,这种调用方式digits 123应该返回[[1],[2],[3]],因为 map 无论如何都会将所有内容组合到一个新列表中,而不是[1,2,3]像它正确的那样。但为什么?
让我们来看看类型read:
Prelude> :t read
read :: Read a => String -> a
Run Code Online (Sandbox Code Playgroud)
也就是说,对于a作为 实例的任何类型Read,该read函数可用于将 a 转换String为该类型的成员。请注意,这里的参数read是 a String- 而不是 a Char!因此,为了使用 将 a 转换Char为其他类型read,您首先需要将 转换Char为 a String。你是怎么做到的?好吧,请记住, aString只是Chars:的列表type String = [Char]。因此,您可以通过Char将 aString包装在一个列表中来将其转换为 a — 这正是您的代码所做的。您可以在 GHCi 中自己确认这是必要的:
Prelude> read '1' :: Int
<interactive>:10:6: error:
* Couldn't match type `Char' with `[Char]'
Expected type: String
Actual type: Char
* In the first argument of `read', namely '1'
In the expression: read '1' :: Int
In an equation for `it': it = read '1' :: Int
Prelude> read "1" :: Int
1
Prelude> read ['1'] :: Int
1
Prelude> :t ['1']
['1'] :: [Char]
Prelude> :t "1"
"1" :: [Char]
Prelude> :t '1'
'1' :: Char
Run Code Online (Sandbox Code Playgroud)
(顺便说一下,我应该注意到你的代码摘要的其余部分是完全正确的。)
read :: Read a => String -> a适用于 a String,而不适用于 a Char,这里x是Char.
实际上,show n构造 a String,它是Chars的列表,因为type String = [Char]。如果我们对Chars的列表执行映射,则映射函数中的x是 a Char。我们将它包装在一个单例列表中以构造一个String带有一个Char演员的 a,然后使用read该字符串作为Int.
然而,我们可以使用digitToInt :: Char -> Int它可能更高效和优雅:
import Data.Char(digitToInt)
digits :: Integer -> [Int]
digits = map digitToInt . showRun Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
66 次 |
| 最近记录: |