10

I want to know how to convert a string to lowercase using the ToLower function (Char -> Char).

This is the code I have so far:

let newlist = (\(h:t) -> c (h) ++ newlist (\c -> toLower c)

I can't see how to do it without using recursion, which I don't know how to use in a lambda expression

duplode
  • 33,731
  • 7
  • 79
  • 150
William
  • 109
  • 1
  • 2
  • 7

3 Answers3

22

It would be easier to not use a lambda expression considering you can eta-reduce to not explicitly name the variable your function accepts. For example you could use a list comprehension:

import Data.Char

lowerString str = [ toLower loweredString | loweredString <- str]

Which you would call as:

ghci> lowerString "Hello"
hello

Alternatively, you could use map:

lowerString = map toLower

If you insist on using a lambda expression, it would look something like this:

import Data.Char

lowerString = \x -> map toLower x

Which again, is not as nice.

mnoronha
  • 2,626
  • 3
  • 17
  • 27
2

With a lambda expression you'd still need to recursively check each character of the string, or you could use map which is still a recursive function that applies the function (a -> b) to every element in the list, for example:

  newList [] = []
  newList xs = (\(y:ys) -> if x `elem` ['A'..'Z'] then toLower y : newList ys else y : newList ys) xs

With map is actually much simpler due to reasons explained in the first paragraph, check mnoronha's answer as he already gave you the answer, but that's if you're thinking of using map in conjunction with toLower.

This is an example without a lambda expression, which requires you to import 2 functions from Data.Char, recursively check the rest of the string and replace each character with its lower case version.

newList :: String -> String
newList [] = []
newList (x:xs) = if x `elem` ['A'..'Z'] 
               then chr (ord x + 32) : newList xs 
               else x : newList xs  

or with guards

newList :: String -> String
newList [] = []
newList (x:xs)
    | x `elem` ['A'..'Z'] = chr (ord x + 32) : newList xs 
    | otherwise = x : newList xs 
Bargros
  • 521
  • 6
  • 18
  • 1
    Have you tested your code? It looks as it will fail as soon as the end of the string is reached, since you never specify what to do with the empty tail `[]`. – chi Oct 20 '16 at 16:26
  • should be ok now, I always forget about that when dealing with lists, thank you – Bargros Oct 20 '16 at 17:43
  • `s==[]` will always be false, since `s = x:xs` so it's not empty. – chi Oct 20 '16 at 18:36
0

This may be more trouble than it's worth but you can use the fix function to recursively call a lambda function.

fix :: (a -> a) -> a
fix f = let x = f x in x

The following code uses the same method used on this page : https://www.vex.net/~trebla/haskell/fix.xhtml to transition from a non-lambda version to a lambda version to (eventually) using fix to recursively call a lambda function without introducing a new variable

import Data.Char (toLower)
import Control.Monad.Fix (fix)

main :: IO ()
main = do 
    -- calling non lambda version
    let newlist1 s = if null s then [] else toLower (head s) : newlist1 (tail s)
    print $ newlist1 "Hello"

    -- calling lambda version
    let newlist2 = \s -> if null s then [] else toLower (head s) : newlist2 (tail s)
    print $ newlist2 "Hello"

    -- defining lambda version locally
    -- ( at this point the scope of newlist3 is local to the let statement )
    print $ (let newlist3 = \s -> if null s then [] else toLower (head s) : newlist3 (tail s) in newlist3 ) "Hello"

    -- making function an argument to be called recursively
    print $ (let newlist3 = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s)) newlist3 in newlist3 ) "Hello"

    -- isolating function to be "fixed".
    let f = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s))
    print $ (let newlist3 =  f newlist3 in newlist3 ) "Hello"

    -- using fix = let x = f x in x
    print $ (fix f) "Hello"

    -- f2 is slightly simpler version of f
    let f2 = (\v s -> if null s then [] else toLower (head s) : v (tail s))
    print $ (fix f2) "Hello"

    -- inlining f2 to get recursive call to lambda 
    print $ (fix (\v s -> if null s then [] else toLower (head s) : v (tail s))) "Hello"
Dave Compton
  • 1,421
  • 1
  • 11
  • 18