使用匿名函数折叠

Folding with anonymous functions

我正在努力学习折叠。

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

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

doubleVowels :: String -> String

我的尝试是(但仅针对 'a',因为我尝试先解决一个字母,然后扩展和优化它,一旦它 运行s):

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.

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函数的参数

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

比如这里是修改后的版本

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