AMINA ARSHAD
AMINA ARSHAD

Reputation: 41

Toggle Cases in Haskell Language

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

Answers (3)

Mahmoud
Mahmoud

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

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477794

You basically here perform mappings. You can toggle the case by defining a mapping that for a given character:

  1. checks if it is an uppercase character, in case it is, return its lowercase equivlant;
  2. check if it is a lowercase character, in case it is, return its uppercase equivalent; and
  3. otherwise return the original 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 mapping over toggleChar:

toggleString :: String -> String
toggleString = map toggleChar

Upvotes: 2

leftaroundabout
leftaroundabout

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

Related Questions