First attempt at Haskell: Converting lower case letters to upper case

I have recently started learning Haskell, and I've tried creating a function in order to convert a lower case word to an upper case word, it works, but I don't know how good it is and I have some questions. Code:

lowerToUpperImpl element list litereMari litereMici = do if not (null list) then if (head list) == element then ['A'..'Z'] !! (length ['A'..'Z'] - length (tail list ) -1) else lowerToUpperImpl element (tail list) litereMari litereMici else '0' --never to be reached lowerToUpper element = lowerToUpperImpl element ['a'..'z'] ['A'..'Z'] ['a'..'z'] lowerToUpperWordImpl word = do if not (null word) then lowerToUpper (head (word)):(lowerToUpperWordImpl (tail word)) else "" 
  1. I don't like the way I have passed the upper case and lower case letters , couldn't I just declare a global variables or something?
  2. What would your approach be in filling the dead else branch?

What would your suggestions on improving this be?

4

2 Answers

Firstly, if/else is generally seen as a crutch in functional programming languages, precisely because they aren't really supposed to be used as branch operations, but as functions. Also remember that lists don't know their own lengths in Haskell, and so calculating it is an O(n) step. This is particularly bad for infinite lists.

I would write it more like this (if I didn't import any libraries):

uppercase :: String -> String uppercase = map (\c -> if c >= 'a' && c <= 'z' then toEnum (fromEnum c - 32) else c) 

Let me explain. This code makes use of the Enum and Ord typeclasses that Char satisfies. fromEnum c translates c to its ASCII code and toEnum takes ASCII codes to their equivalent characters. The function I supply to map simply checks that the character is lowercase and subtracts 32 (the difference between 'A' and 'a') if it is, and leaves it alone otherwise.

Of course, you could always just write:

import Data.Char uppercase :: String -> String uppercase = map toUpper 

Hope this helps!

The things I always recommend to people in your circumstances are these:

  1. Break the problem down into smaller pieces, and write separate functions for each piece.
  2. Use library functions wherever you can to solve the smaller subproblems.
  3. As an exercise after you're done, figure out how to write on your own the library functions you used.

In this case, we can apply the points as follows. First, since String in Haskell is a synonym for [Char] (list of Char), we can break your problem into these two pieces:

  • Turn a character into its uppercase counterpart.
  • Transform a list by applying a function separately to each of its members.

Second point: as Alex's answer points out, the Data.Char standard library module comes with a function toUpper that performs the first task, and the Prelude library comes with map which performs the second. So using those two together solves your problem immediately (and this is exactly the code Alex wrote earlier):

import Data.Char uppercase :: String -> String uppercase = map toUpper 

But I'd say that this is the best solution (shortest and clearest), and as a beginner, this is the first answer you should try.

Applying my third point: after you've come up with the standard solution, it is enormously educational to try and write your own versions of the library functions you used. The point is that this way you learn three things:

  1. How to break down problems into easier, smaller pieces, preferably reusable ones;
  2. The contents of the standard libraries of the language;
  3. How to write the simple "foundation" functions that the library provides.

So in this case, you can try writing your own versions of toUpper and map. I'll provide a skeleton for map:

map :: (a -> b) -> [a] -> [b] map f [] = ??? map f (x:xs) = ??? 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like