Reputation: 41
I am new in Haskell and have some problem in defining the function which takes parameter of type string, returns the result of type string and convert uppercase letters into lower case letters and lower case letter into upper case letters. I have defined function for lower and upper conversion separately.
Code:
--upper case
func_upper :: String -> String
func_upper = map (\x-> if x>='a' && x<='z' then
toEnum(fromEnum x-32) else
x)
--Lower case
func_lower :: String -> String
func_lower = map (\x ->if x>='A' && x<='Z' then
toEnum (fromEnum x+32) else
x)
but i am unable to combine these two functions and make one function that will perform both operations. I have practiced but failed.My practice code is:
func_ ::String -> String
func_ x = if(x>='a' && x<='z') then toEnum (fromEnum x-32) else
if (x>='A' && x<='Z') then toEnum (fromEnum x+32) else
x
Kindly help me to solve this issue and your help would be much appreciated.
Upvotes: 0
Views: 574
Reputation: 11489
This approach handles special characters and numbers without any imports:
special = ['0'..'9'] ++ [' ', '!','@','#','$','%','^','&','*','(',')','_','-','+']
alphabet = ['a'..'z'] ++ special ++ ['A'..'Z'] ++ special
idx c (x:xs) | c /= x = 1 + idx c xs
| otherwise = 0
toggleChar s = alphabet !! mod (idx s alphabet + 26 + length special) (length alphabet)
toggleString = map toggleChar
Upvotes: 0
Reputation: 477794
You basically here perform map
pings. You can toggle the case by defining a mapping that for a given character:
We can implement such function like:
import Data.Char(isLower, isUpper, toLower, toUpper)
toggleChar :: Char -> Char
toggleChar x | isUpper x = toLower x
| isLower x = toUpper x
| otherwise = x
or without using Data.Char
imports:
toggleChar :: Char -> Char
toggleChar x | 'A' <= x && x <= 'Z' = toEnum (fromEnum x - 32)
| 'a' <= x && x <= 'z' = toEnum (fromEnum x + 32)
| otherwise = x
then we can implement toggle over an entire string by map
ping over toggleChar
:
toggleString :: String -> String
toggleString = map toggleChar
Upvotes: 2
Reputation: 120751
First, note that it's sufficient to define the functions only for single characters. You can then wrap them in map
later to work with strings.
So, you have
toUpper :: Char -> Char
toUpper x = if x>='a' && x<='z' then
toEnum(fromEnum x-32) else
x
toLower :: Char -> Char
toLower x = if x>='A' && x<='Z' then
toEnum (fromEnum x+32) else
x
...or, as they're better written
toUpper x
| x>='a' && x<='z' = toEnum $ fromEnum x - 32
| otherwise = x
toLower x
| x>='A' && x<='Z' = toEnum $ fromEnum x + 32
| otherwise = x
Now, the nice thing with this guard syntax is that you can just add more clauses. So all you need to do is put the conditional clauses of both functions in one. The first one that succeds will then specify how to compute the result.
The equivalent thing can also be done with if
, but it requires an awkward nesting in the else
branch.
Upvotes: 3