【问题标题】:Why does this function used by map need to return a (singleton) list instead of an element?为什么map使用的这个函数需要返回一个(单例)列表而不是一个元素?
【发布时间】:2021-05-23 05:55:34
【问题描述】:

您可能已经猜到了。我已经完成了“Learn you a Haskell”,但我仍然在努力学习基础知识。

我正在看这个帖子 Split a number into its digits with Haskell 有了这个功能,事情就开始变得有意义了

digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)

丹尼尔问。

我知道 show 会将我的输入数字作为字符串或字符列表返回,然后我可以使用 map 逐个元素地修改它。因此,每个作为 Char 的“x”被匿名函数挑选并作为 Integer 读取,新列表由 map 组成,包含所有读取的整数。那么read [x] 不应该是read x 吗?为什么列表中的每个读取 Char 都需要作为它自己的单例列表返回?在我看来,这种调用digits 123 的方式应该返回[[1],[2],[3]],因为map 无论如何都会将所有内容组合到一个新列表中,而不是正确的[1,2,3]。但为什么呢?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    read :: Read a => String -> aString 上工作,而不是在Char 上工作,这里xChar

    确实,show n 构造了一个String,它是Chars 的列表,因为type String = [Char]。如果我们对Chars 列表进行映射,那么x 就是映射函数中的Char。我们将它包装在一个单例列表中以构造一个带有一个Character 的String,然后使用read 将该字符串读取为Int

    然而,我们可以使用digitToInt :: Char -> Int,这可能更高效、更优雅:

    import Data.Char(digitToInt)
    
    digits :: Integer -> [Int]
    digits = map digitToInt . show

    【讨论】:

    • 呵呵,我以前不知道digitToInt。感谢您提及!
    【解决方案2】:

    我们来看看read的类型:

    Prelude> :t read
    read :: Read a => String -> a
    

    也就是说,对于作为Read 实例的任何类型aread 函数可用于将String 转换为该类型的成员。请注意,read 的参数是 String,而不是 Char!因此,为了使用readChar 转换为其他类型,您首先需要将Char 转换为String。你是怎么做到的?好吧,请记住 String 只是 Chars 的列表:type String = [Char]。因此,您可以通过将Char 包装在一个列表中来将Char 转换为String——这正是您的代码正在做的事情。您可以在 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
    

    (顺便说一下,我应该注意到你对代码的其余部分是完全正确的。)

    【讨论】:

      【解决方案3】:

      好吧,这是一个愚蠢的问题... 单例列表在那里,因为 read 需要它作为输入,一个字符串,而不是单个字符,结果确实是一个 Int。婴儿步...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        • 2019-11-23
        • 2015-04-15
        • 2020-10-13
        • 1970-01-01
        • 1970-01-01
        • 2020-10-11
        相关资源
        最近更新 更多