Reputation: 109
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
Upvotes: 10
Views: 16728
Reputation: 2625
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.
Upvotes: 22
Reputation: 1441
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"
Upvotes: 0
Reputation: 531
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
Upvotes: 2