【问题标题】:Folding with anonymous functions使用匿名函数折叠
【发布时间】:2021-12-30 17:10:33
【问题描述】:

我目前正在尝试学习折叠。

但我不想使用预定义的函数,而是想使用我自己的。

所以我想将字符串中的所有元音加倍。

doubleVowels :: String -> String

我的尝试是(但仅针对“a”,因为我尝试先解决一个字母,然后在运行后对其进行扩展和优化):

doubleVowels :: String -> String
doubleVowels  a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a

尝试运行他的代码我得到以下错误:

Experimenting.hs:8:78: error:
    * Couldn't match type `[Char]' with `Char -> Char'
      Expected type: Char -> Char
        Actual type: String
    * In the expression: a
      In the expression: if eachChar == 'a' then (a ++ "aa") else a
      In the first argument of `foldl', namely
        `(\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a)'
  |
8 | doubleVowels a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
  |                                                                              ^

Experimenting.hs:8:81: error:
    * Couldn't match expected type `Char' with actual type `[Char]'
    * In the second argument of `foldl', namely `""'
      In the expression:
        foldl
          (\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
      In an equation for `doubleVowels':
          doubleVowels
            = foldl
                (\ eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
  |
8 | doubleVowels a = foldl (\eachChar -> if eachChar == 'a' then (a ++ "aa") else a) "" a
  |                                                                                 ^^
Failed, no modules loaded.

【问题讨论】:

    标签: haskell anonymous-function higher-order-functions folding


    【解决方案1】:

    首先,foldl 中使用的函数应该有两个参数。第一个是累积结果,另一个是当前字符。 其次,foldl的求值顺序是从左到右,所以我们要reverse结果字符串。

    例如,这里是修改后的版本

     doubleVowels :: String -> String
     doubleVowels s = reverse $ foldl (\x y -> if y == 'a' then ("aa" ++ x) else (y : x)) "" s
    

    【讨论】:

      【解决方案2】:
      doubleVowels :: String -> String
      doubleVowels  a = foldr (\eachChar b -> if eachChar == 'a' then ("aa" ++ b) else (eachChar:b)) "" a
      

      在大多数情况下,如果 foldl 没有特定原因,请使用 foldr 而不是 foldl,因为它允许 Haskell 编译器懒惰地评估您的表达式。如果我没记错的话,即使这样也可以使用foldl',因为foldl 并不严格,而且会占用太多内存,而不会给你带来任何懒惰的好处。

      除此之外,您还缺少foldrs(或foldls)函数的第二个参数。 foldr 有类型:

      foldr :: (a -> b -> b) -> b -> t a -> b
      

      foldr 的函数类型为a -> b -> b,其中第一个参数是折叠结构的当前元素,第二个参数是累加器。您使用的 lambda 只有一个参数。

      另外,lambda 函数的主体也没有多大意义。

      if eachChar == 'a' then (a ++ "aa") else a)
      

      a是环绕函数doubleVowels接收的参数。这里需要用到lambda函数的参数。

      【讨论】:

        猜你喜欢
        • 2014-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 2017-01-03
        • 2014-08-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多