Haskell - string to list isusses, and more

Hello everyone! Im a Haskell newbie, and Ive have few unanswered questions. For someone more experienced (at least I think so) its a very simple task, but I just cant get a grip on it and its pretty frustrating. It wouldn't be that bad if I haven't browse thru bunch of pages and tutorials and still nothing... The problem is: take a string, and if every words starts with uppercase letter then print yes, else no. Forum Text Bold -> yes Frog image File -> no Ive had my share of approaches to this, but I just cant make it work. Standard one seemed the most simple: search :: String -> String search [] = [] and then use words (splits string on space) to split the string so I could get a list and go through it recursively. But how to apply words to entered string in this form? To find the first letter I came up with: first = take 1 (head x). And compare it with elem or ASCII values to determine if its upper case. Any help, advice or suggestion is appreciated. Thanks in advance! -- View this message in context: http://www.nabble.com/Haskell---string-to-list-isusses%2C-and-more-tp2402267... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

2009/6/14 Gjuro Chensen
Hello everyone!
Im a Haskell newbie, and Ive have few unanswered questions. For someone more experienced (at least I think so) its a very simple task, but I just cant get a grip on it and its pretty frustrating. It wouldn't be that bad if I haven't browse thru bunch of pages and tutorials and still nothing... The problem is: take a string, and if every words starts with uppercase letter then print yes, else no. Forum Text Bold -> yes Frog image File -> no
Ive had my share of approaches to this, but I just cant make it work. Standard one seemed the most simple:
search :: String -> String search [] = []
and then use words (splits string on space) to split the string so I could get a list and go through it recursively. But how to apply words to entered string in this form?
To find the first letter I came up with: first = take 1 (head x). And compare it with elem or ASCII values to determine if its upper case.
Any help, advice or suggestion is appreciated.
Thanks in advance!
-- View this message in context: http://www.nabble.com/Haskell---string-to-list-isusses%2C-and-more-tp2402267... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
As you say, there are a number of possible approaches to take here. I'd say take a look at functions "all" [1] and "isUpper" [2], those should be all you need. * "all" takes a predicate (a function) and a list of elements. It returns True if that predicate holds for all of the elements in the list, otherwise False. * "isUpper" takes a Char and returns True if that character is an uppercase letter, otherwise False. [1] http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html [2] http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Char.html -- Deniz Dogan

Gjuro Chensen wrote:
Hello everyone!
Im a Haskell newbie, and Ive have few unanswered questions. For someone more experienced (at least I think so) its a very simple task, but I just cant get a grip on it and its pretty frustrating. It wouldn't be that bad if I haven't browse thru bunch of pages and tutorials and still nothing... The problem is: take a string, and if every words starts with uppercase letter then print yes, else no. Forum Text Bold -> yes Frog image File -> no
Ive had my share of approaches to this, but I just cant make it work. Standard one seemed the most simple:
search :: String -> String search [] = []
and then use words (splits string on space) to split the string so I could get a list and go through it recursively. But how to apply words to entered string in this form?
To find the first letter I came up with: first = take 1 (head x). And compare it with elem or ASCII values to determine if its upper case.
The idea of using `words' is very good. If we want to use a bottom-up approach, we should have a function that determines if a word starts with an upper-case letter, i.e. a function of type startsWithUppercase :: String -> Bool startsWithUppercase = ... (Hint: look at 'isUpper' from Data.Char) Now we need a way to see if for each word, some predicate is satisfied. There is a standard function for this, "all". You can also do this by using "map" and "and". The resulting function can be very concise if you get the hang of it :) Regards, -- Jochem Berndsen | jochem@functor.nl GPG: 0xE6FABFAB

Am Sonntag 14 Juni 2009 17:19:22 schrieb Gjuro Chensen:
Hello everyone!
Im a Haskell newbie, and Ive have few unanswered questions. For someone more experienced (at least I think so) its a very simple task, but I just cant get a grip on it and its pretty frustrating. It wouldn't be that bad if I haven't browse thru bunch of pages and tutorials and still nothing... The problem is: take a string, and if every words starts with uppercase letter then print yes, else no. Forum Text Bold -> yes Frog image File -> no
Ive had my share of approaches to this, but I just cant make it work. Standard one seemed the most simple:
search :: String -> String search [] = []
and then use words (splits string on space) to split the string so I could
That's good. So you have everyWordStartsWithAnUppercaseLetter string = doSomething (words string) doSomething :: [String] -> Bool checks wordStartsWithAnUppercaseLetter :: String -> Bool for each word in the list and returns True if all words satisfy the condition, False if not. There's a handy function in the prelude for that: Prelude> :t all all :: (a -> Bool) -> [a] -> Bool
get a list and go through it recursively. But how to apply words to entered string in this form?
To find the first letter I came up with: first = take 1 (head x). And
No, I don't think that's what you want: Prelude> :t (take 1 . head) (take 1 . head) :: [[a]] -> [a] Since String is a synonym for [Char], "head" gets the first letter of a word.
compare it with elem or ASCII values to determine if its upper case.
What about unicode strings? Prelude> :t Data.Char.isUpper Data.Char.isUpper :: Char -> Bool is what you want.
Any help, advice or suggestion is appreciated.
Thanks in advance!
How to assemble that is left to you.

Here's what I came up with. I especially like the 2nd version, even though it's longer, as it seems very declarative. caps1 s = all (\x -> isUpper (head x)) (words s) caps2 s = all startsWithUpper (words s) where startsWithUpper w = isUpper (head w) I'm also fairly new to Haskell, so I would appreciate feedback from the more experienced. Thanks. On Jun 14, 2009, at 11:19 AM, Gjuro Chensen wrote:
Hello everyone!
Im a Haskell newbie, and Ive have few unanswered questions. For someone more experienced (at least I think so) its a very simple task, but I just cant get a grip on it and its pretty frustrating. It wouldn't be that bad if I haven't browse thru bunch of pages and tutorials and still nothing... The problem is: take a string, and if every words starts with uppercase letter then print yes, else no. Forum Text Bold -> yes Frog image File -> no
Ive had my share of approaches to this, but I just cant make it work. Standard one seemed the most simple:
search :: String -> String search [] = []
and then use words (splits string on space) to split the string so I could get a list and go through it recursively. But how to apply words to entered string in this form?
To find the first letter I came up with: first = take 1 (head x). And compare it with elem or ASCII values to determine if its upper case.
Any help, advice or suggestion is appreciated.
Thanks in advance!
-- View this message in context: http://www.nabble.com/Haskell---string-to-list-isusses%2C-and-more-tp2402267... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Toby Miller wrote:
Here's what I came up with. I especially like the 2nd version, even though it's longer, as it seems very declarative.
caps1 s = all (\x -> isUpper (head x)) (words s)
caps2 s = all startsWithUpper (words s) where startsWithUpper w = isUpper (head w)
I'm also fairly new to Haskell, so I would appreciate feedback from the more experienced.
This seems fine, but you need to check that words never returns a list containing the empty string (otherwise `head' will fail). I prefer in this case a point free style though, but some might disagree. Cheers, -- Jochem Berndsen | jochem@functor.nl GPG: 0xE6FABFAB

2009/6/14 Jochem Berndsen
Toby Miller wrote:
caps1 s = all (\x -> isUpper (head x)) (words s) This seems fine, but you need to check that words never returns a list containing the empty string (otherwise `head' will fail).
Is there any such case? I was thinking about that as well, but couldn't think of any case where head would be called on an empty list. -- Deniz Dogan

Deniz Dogan wrote:
2009/6/14 Jochem Berndsen
: Toby Miller wrote:
caps1 s = all (\x -> isUpper (head x)) (words s) This seems fine, but you need to check that words never returns a list containing the empty string (otherwise `head' will fail).
Is there any such case? I was thinking about that as well, but couldn't think of any case where head would be called on an empty list.
Not that I know of; but I tested this in order to make sure that I didn't overlook something obvious. (At least, it's a potential issue that we need to check, since `head' is partial.) Regards, -- Jochem Berndsen | jochem@functor.nl GPG: 0xE6FABFAB

2009/6/14 Toby Miller
Here's what I came up with. I especially like the 2nd version, even though it's longer, as it seems very declarative.
caps1 s = all (\x -> isUpper (head x)) (words s)
caps2 s = all startsWithUpper (words s) where startsWithUpper w = isUpper (head w)
I'm also fairly new to Haskell, so I would appreciate feedback from the more experienced.
Thanks.
Not that I'm very experienced myself, but I came up with the first idea as well: caps1 = all (isUpper . head) . words -- Deniz Dogan

Toby Miller wrote:
Here's what I came up with. I especially like the 2nd version, even though it's longer, as it seems very declarative.
caps1 s = all (\x -> isUpper (head x)) (words s)
caps2 s = all startsWithUpper (words s) where startsWithUpper w = isUpper (head w)
I'm also fairly new to Haskell, so I would appreciate feedback from the more experienced.
Thanks.
caps = all (isUpper . head) . words But then, I'm strange like that...

Gjuro Chensen wrote:
/cut
I dont know everyone will see this, but I would like thank everyone who found time to help, and not spam too much doing it:D. Well, I did it! Its not great (especially comparing to those one line solutions, wow!), but it works. module Main where startsWithUpper :: String -> Bool startsWithUpper []= False startsWithUpper string = if myIsUpper(head(string)) then True else False myIsUpper :: Char -> Bool myIsUpper x = if x>='A' && x <= 'Z' then True else False checkAll string = check (words string) check :: [String] -> Bool check []=False check x = if all startsWithUpper x then True else False Since importing modules isnt allowed, I made my own isUpper. And thats it, for few days of Haskell, Im happy. Once again, many many thanks to everyone! -- View this message in context: http://www.nabble.com/Haskell---string-to-list-isusses%2C-and-more-tp2402267... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Gjuro Chensen wrote:
startsWithUpper :: String -> Bool startsWithUpper []= False startsWithUpper string = if myIsUpper(head(string)) then True else False
It is very good that you caught the issue of taking the head of an empty list :) I saw here and also below, that you did things like if P then True else False You can shorten this to 'P'. Also, normally Haskellers like to pattern match, changing the second clause of your function into startsWithUpper (x:xs) = myIsUpper x
check :: [String] -> Bool check []=False
Why is this False and not True? Certainly in the empty string all words start with an uppercase letter, don't they? (If it's True, you can even remove this clause, and let the other one take care of the rest.) Regards, -- Jochem Berndsen | jochem@functor.nl GPG: 0xE6FABFAB

On Sun, Jun 14, 2009 at 11:14 AM, Gjuro Chensen
Gjuro Chensen wrote:
/cut
I dont know everyone will see this, but I would like thank everyone who found time to help, and not spam too much doing it:D. Well, I did it! Its not great (especially comparing to those one line solutions, wow!), but it works.
Nice work. For fun, I'm going to semi-formally transform your solution into the one-liner that was given (multiple times). Systematic transformation is one of the great joys of functional programming. I don't know if you'll find this interesting, but I do, so here goes: myIsUpper = isUpper for ASCII, so let's just assume that.
module Main where
startsWithUpper :: String -> Bool startsWithUpper []= False startsWithUpper string = if myIsUpper(head(string)) then True else False
We can transform this to: startsWithUpper string = isUpper (head string) Under the precondition that the input is not []. So this function has become less general. Now a few systematic transformations to make this smaller: startsWithUpper string = isUpper (head string) startsWithUpper = \string -> isUpper (head string) startsWithUpper = isUpper . head That last step because: f . g = \x -> f (g x) checkAll string = check (words string) checkAll = \string -> check (words string) checkAll = check . words For the same reason as above. check :: [String] -> Bool
check []=False check x = if all startsWithUpper x then True else False
Rewriting the second clause after observing that "if p then True else False" is the same as "p". check [] = False check x = all startsWithUpper x I'm going to take Jochem's suggestion and change the empty clause to True: "all words start with an upper case letter" is equivalent to "there is no word which does not start with an upper case letter", which is true for an empty list. check [] = True check x = all startsWithUpper x Now, in ghci: ghci> all undefined [] True Since this returned True for undefined, it will return True for any argument whatsoever there (this is called the "monotone" property, and all Haskell functions obey it). Therefore, we can remove the empty list clause: check x = all startsWithUpper x And systematic transformations: check = \x -> all startsWithUpper x check = all startsWithUpper So that leaves us with: starsWithUpper = isUpper . head checkAll = check . words check = all startsWithUpper Substituting the local definitions: checkAll = all (isUpper . head) . words The last thing: we made startsWithUpper less general in the process; it is undefined for empty strings. We need to verify that words never returns any empty strings. I did this using SmallCheck: ghci> import Test.SmallCheck ghci> smallCheck 10 $ \string -> all (not . null) (words string) Depth 0: Completed 1 test(s) without failure. Depth 1: Completed 2 test(s) without failure. Depth 2: Completed 5 test(s) without failure. Depth 3: Completed 16 test(s) without failure. Depth 4: Completed 65 test(s) without failure. Depth 5: Completed 326 test(s) without failure. Depth 6: Completed 1957 test(s) without failure. Depth 7: Completed 13700 test(s) without failure. Depth 8: Completed 109601 test(s) without failure. Depth 9: Completed 986410 test(s) without failure. Depth 10: Completed 9864101 test(s) without failure. So I am reasonably confident that words never gives me any empty strings. Tada! Your solution is almost exactly the same as the one-liners! :-) Luke

On Mon, Jun 15, 2009 at 3:03 AM, Luke Palmer
The last thing: we made startsWithUpper less general in the process; it is undefined for empty strings. We need to verify that words never returns any empty strings. I did this using SmallCheck:
ghci> import Test.SmallCheck ghci> smallCheck 10 $ \string -> all (not . null) (words string)
'Course, it turns out that SmallCheck never generates any spaces... ever. Some verifier that is. By careful inspection of the definition of words, I can see that it never returns an empty string. I couldn't find a better way to convince myself of this (I like to avoid looking at definitions when possible). Luke
Depth 0: Completed 1 test(s) without failure. Depth 1: Completed 2 test(s) without failure. Depth 2: Completed 5 test(s) without failure. Depth 3: Completed 16 test(s) without failure. Depth 4: Completed 65 test(s) without failure. Depth 5: Completed 326 test(s) without failure. Depth 6: Completed 1957 test(s) without failure. Depth 7: Completed 13700 test(s) without failure. Depth 8: Completed 109601 test(s) without failure. Depth 9: Completed 986410 test(s) without failure. Depth 10: Completed 9864101 test(s) without failure.
So I am reasonably confident that words never gives me any empty strings.
Tada! Your solution is almost exactly the same as the one-liners! :-)
Luke

Am Montag 15 Juni 2009 11:03:36 schrieb Luke Palmer:
We can transform this to:
startsWithUpper string = isUpper (head string)
Under the precondition that the input is not []. So this function has become less general.
What about all isUpper . take 1 ? But of course the source reveals that words never puts an empty string into the list.
participants (7)
-
Andrew Coppin
-
Daniel Fischer
-
Deniz Dogan
-
Gjuro Chensen
-
Jochem Berndsen
-
Luke Palmer
-
Toby Miller