Home > front end >  Folding with anonymous functions
Folding with anonymous functions

Time:11-20

I'm currently trying to learn folding.

But instead of using predefined functions I want to use my own.

So I want to double all vowels in a String.

doubleVowels :: String -> String

My attempt is (yet just for 'a', as I'm try solve it for one letter first and will expand and optimize it, once it runs):

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

Trying to run he code I'm getting the following erorr:

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.

CodePudding user response:

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

In most cases, if there is no specific reason for foldl, use foldr instead of foldl as it allows the Haskell compiler to lazily evaluate your expression. If I remember correctly, even then use foldl', since foldl is not strict and takes too much memory while not giving you any benefit for the laziness.

Apart from that, you are missing the second argument to foldrs (or foldls) function. foldr has type:

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

The function to foldr has type a -> b -> b where the first argument is the current element of the folding structure and the second is the accumulator. The lambda that you are using has only one parameter.

In addition, the body of the lambda function also doesn't make much sense.

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

a is the parameter that the surrounding function doubleVowels receives. You need to use the parameters of the lambda function here.

CodePudding user response:

First of all, the function used in foldl should have two argments. The first one is the accmulated result, and the other is current char. Second, the order of evaluation of foldl is from left to right, so we have to reverse the result string.

For example, here is a modified version

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