2

I have a list of Strings I want to filter through. My predicate is that the string should begin with an uppercase letter.

eg. when I run onlyLowercase ["boy", "girl", "Hi"]

it should give me a list of ["boy", "girl"]

I can do it using pattern matching and guards, but I'm using the learnyouahaskell (http://learnyouahaskell.com) book and I came across the topic on higher-order functions. I read about the filter function and thought it could achieve what I want to do in far fewer lines of code.

Using pattern Matching/Guards (This works well and solves my problem)

onlyLowercase :: [[Char]] -> [[Char]]
onlyLowercase [] = []
onlyLowercase (x:xs) 
  | isLower (head x) = x : onlyLowercase xs  
  | otherwise = onlyLowercase xs

Using the filter function

onlyLowercase2 :: [String] -> [String]
onlyLowercase2 [] = []
onlyLowercase2 (x:xs) = filter isLower x : onlyLowercase2 xs

Unfortunately, when I run onlyLowercase2 ["boy", "girl", "Hi"], I get a list of ["boy", "girl", "i"].

I want to know if there's a way I can filter my list of strings using the first character in my string (without creating any auxiliary function that could check the String and return true if the first letter is lowercase).

I also tried using

 onlyLowercase2 (x:xs) = filter (isLower head x) : onlyLowercase2 xs

but that didn't even compile. Basically, I'm just trying to figure out how the filter function can be used on a list of lists. Thank you, in advance, for any assistance rendered.

15
  • Yes, but you should not filter on the element x, you filter over the list, and in the filter you take the head. Commented Oct 7, 2018 at 18:34
  • 3
    But you should not use x of the outer list. Define a lambda expression as filter function, so filter (\x -> ...). Commented Oct 7, 2018 at 18:48
  • 3
    You may also go applicative style like filter ((&&) <$> isLower . head <*> (/="")) without a lambda. Commented Oct 7, 2018 at 19:05
  • 1
    This is way advanced for me haha. (only a couple of weeks into learning haskell), but I will read up on this so I can fully understand everything you've written. Thank you so much. Commented Oct 7, 2018 at 19:06
  • 2
    It's perfectly explained in learnyouahaskell.com/… FYI. Commented Oct 7, 2018 at 19:08

2 Answers 2

5

Thanks to Willem Van Onsem's suggestion to use a lambda expression as a filter function, I read further and came up with this 2 line solution.

onlyLowercase2 :: [String] -> [String]
onlyLowercase2 = filter (\st-> ("" /= st) && (isLower $ head st))

Not sure if it's perfect, but at least it's working.

Sign up to request clarification or add additional context in comments.

Comments

1

Using Data.List and Data.Char:

import Data.List
import Data.Char

onlyLowerCase :: [String] -> [String]
onlyLowerCase = filter (all isLower)

I use the all function which checks that all elements of a list satisfy a predicate. In this case all isLower will return true if all letters in a String are lowercase. Then just filter the Strings that are all lowercase. The Haskell Report has a good reference for List and Char functions among other useful libraries.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.