How to check whether text starts with uppercase : # TL;DR:

Surely somebody has written, and packaged up, a utility which
checks whether the first character in a piece of `Text` is uppercase!
Surely something like that is usable with `Protolude` (or some other
modern Prelude replacement).

# The simple problem

I need to find out whether some word starts with an uppercase character.

# Warming up

    import Data.Char
    
    startsWithUppercase :: String -> Bool
    startsWithUppercase = isUpper . head

this works ...

    λ startsWithUppercase "Yes"
    True
    λ startsWithUppercase "no"
    False

except that `head` is a partial function

    λ startsWithUppercase ""
    *** Exception: Prelude.head: empty list

# A safer version

    import Data.Char
    import Data.Maybe
    
    safeHead :: [a] -> Maybe a
    safeHead []    = Nothing
    safeHead (x:_) = Just x
    
    startsWithUppercase :: String -> Bool
    startsWithUppercase = (maybe False isUpper) . safeHead
    
This seems to fix the problem:
    
    λ map startsWithUppercase $ words "Yes no"
    [True,False]
    λ startsWithUppercase ""
    False

except that I want to use `Text` rather than `String`

# Moving from `String` to `Text`

Let's try a direct translation:

    {-# LANGUAGE OverloadedStrings #-}
    
    import Prelude hiding (head)
    import Data.Text
    import Data.Char
    import Data.Maybe
    
    safeHead :: Text -> Maybe Char
    safeHead "" = Nothing
    safeHead t  = Just . head $ t
    
    startsWithUppercase :: Text -> Bool
    startsWithUppercase = (maybe False isUpper) . safeHead
    
It seems to work ...
    
    yes, no, crash :: Text
    yes   = "Yes"
    no    = "no"
    crash = ""
    
    λ Prelude.map startsWithUppercase [yes, no, crash]
    [True,False,False]

... but I can't help wondering why Hoogle didn't come up with anything
interesting in response to `Text -> Maybe Char`.

Anyway, I'm sick and tired of these partial functions all over the
place: I don't want these gaping holes in my static guarantees. I
know, let's use one of these modern Prelude replacemens. `Protolude`
looks good, and seems to have many proponents.

# Moving to Protolude

Protolude, among its many virtues, is supposed to address the two main
issues I have addressed above:

+ Eradicate `String`, make `Text` available by default.
+ Eradicate partial functions, make safe ones available by default.

It even imports `Data.Maybe` for me.

Sounds great. Let's do it!

There will be no need to write `safeHead`, because in `Protolude`
`head` already is safe, and generic to boot:

    λ :t head
    head :: Foldable f => f a -> Maybe a

Excellent!

    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    
    import Protolude
    import Data.Char

    startsWithUppercase :: Text -> Bool
    startsWithUppercase = (maybe False isUpper) . head

Oh dear:

     Lib.hs     8  23 error           [-Wdeferred-type-errors]
         • Couldn't match type ‘Text’ with ‘f0 Char’
           Expected type: Text -> Bool
             Actual type: f0 Char -> Bool
         • In the expression: (maybe False isUpper) . head
           In an equation for ‘startsWithUppercase’:
               startsWithUppercase = (maybe False isUpper) . head (intero)

`Protolude.head` is defined on `Foldable`s, which `Text` isn't.

I guess I'll have to write my own `safeHead` for `Text` after all.

Hmm, but for that I used `Text.head` and `Protolude` hides that away.

After numerous further failed attempts to get this to work, I have to stand back and think: I'm trying to find whether the
first character of a piece of `Text` is uppercase, in a modern
Prelude. **Surely it can't take this much effort!!!1111!!!**

What am I missing? What is the sane solution to this simple problem?
