Skip to content

Instantly share code, notes, and snippets.

@1eyewonder
Last active April 9, 2025 19:14
Show Gist options
  • Save 1eyewonder/bb13f50ddbe8fee6526fa5c074ac254f to your computer and use it in GitHub Desktop.
Save 1eyewonder/bb13f50ddbe8fee6526fa5c074ac254f to your computer and use it in GitHub Desktop.
F# String Active Patterns
open System
open System.Text.RegularExpressions
let (|Lower|) (s: string) = s.ToLower()
let (|LowerInvariant|) (s: string) = s.ToLowerInvariant()
let (|Upper|) (s: string) = s.ToUpper()
let (|UpperInvariant|) (s: string) = s.ToUpperInvariant()
let (|Trim|) (s: string) = s.Trim()
let (|TrimChars|) (chars: char array) (s: string) = s.Trim(chars)
/// Check if a string is null
[<return: Struct>]
let (|NullString|_|) (s: string) =
if s = null then ValueSome () else ValueNone
/// Check if a string is empty and not null
[<return: Struct>]
let (|EmptyString|_|) (s: string) =
match s with
| NullString _ -> ValueNone
| s when String.IsNullOrEmpty s -> ValueSome ()
| _ -> ValueNone
/// Check if a string is whitespace and not null
[<return: Struct>]
let (|Whitespace|_|) (s: string) =
match s with
| NullString _ -> ValueNone
| s when String.IsNullOrWhiteSpace s -> ValueSome ()
| _ -> ValueNone
/// Check if a string is not empty or null
[<return: Struct>]
let (|NonEmptyString|_|) (s: string) =
match s with
| NullString _ -> ValueNone
| EmptyString _ -> ValueNone
| _ -> ValueSome s
/// Check if a string is not whitespace, empty or null
[<return: Struct>]
let (|SafeString|_|) (s: string) =
match s with
| EmptyString _ -> ValueNone
| Whitespace _ -> ValueNone
| _ -> ValueSome s
/// Check if a string is not whitespace, empty or null and converts it to lowercase
[<return: Struct>]
let (|SafeLower|_|) (s: string) =
match s with
| SafeString s -> (|Lower|) s |> ValueSome
| _ -> ValueNone
/// Check if a string is not whitespace, empty or null and converts it to uppercase
[<return: Struct>]
let (|SafeUpper|_|) (s: string) =
match s with
| SafeString s -> (|Upper|) s |> ValueSome
| _ -> ValueNone
/// Checks if a string is not whitespace, empty or null and trims it
[<return: Struct>]
let (|SafeTrim|_|) (s: string) =
match s with
| SafeString s -> (|Trim|) s |> ValueSome
| _ -> ValueNone
/// Checks if a string is not whitespace, empty or null and trims the specified characters out
[<return: Struct>]
let (|SafeTrimChars|_|) chars (s: string) =
match s with
| SafeString s -> (|TrimChars|) chars s |> ValueSome
| _ -> ValueNone
[<return: Struct>]
let (|StringEquals|_|) (comparisonType: StringComparison) (s1: string) (s2: string) =
if s1.Equals(s2, comparisonType) then ValueSome () else ValueNone
[<return: Struct>]
let (|EqualsCurrentCulture|_|) = (|StringEquals|_|) StringComparison.CurrentCulture
[<return: Struct>]
let (|EqualsCurrentCultureIgnoreCase|_|) = (|StringEquals|_|) StringComparison.CurrentCultureIgnoreCase
[<return: Struct>]
let (|EqualsInvariantCulture|_|) = (|StringEquals|_|) StringComparison.InvariantCulture
[<return: Struct>]
let (|EqualsInvariantCultureIgnoreCase|_|) = (|StringEquals|_|) StringComparison.InvariantCultureIgnoreCase
[<return: Struct>]
let (|EqualsOrdinal|_|) = (|StringEquals|_|) StringComparison.Ordinal
[<return: Struct>]
let (|EqualsOrdinalIgnoreCase|_|) = (|StringEquals|_|) StringComparison.OrdinalIgnoreCase
[<return: Struct>]
let (|StringContains|_|) (comparisonType: StringComparison) (value: string) (s: string) =
if s.Contains(value, comparisonType) then ValueSome () else ValueNone
[<return: Struct>]
let (|ContainsCurrentCulture|_|) = (|StringContains|_|) StringComparison.CurrentCulture
[<return: Struct>]
let (|ContainsCurrentCultureIgnoreCase|_|) = (|StringContains|_|) StringComparison.CurrentCultureIgnoreCase
[<return: Struct>]
let (|ContainsInvariantCulture|_|) = (|StringContains|_|) StringComparison.InvariantCulture
[<return: Struct>]
let (|ContainsInvariantCultureIgnoreCase|_|) = (|StringContains|_|) StringComparison.InvariantCultureIgnoreCase
[<return: Struct>]
let (|ContainsOrdinal|_|) = (|StringContains|_|) StringComparison.Ordinal
[<return: Struct>]
let (|ContainsOrdinalIgnoreCase|_|) = (|StringContains|_|) StringComparison.OrdinalIgnoreCase
[<return: Struct>]
let (|StringStartsWith|_|) (comparisonType: StringComparison) (value: string) (s: string) =
if s.StartsWith(value, comparisonType) then ValueSome () else ValueNone
[<return: Struct>]
let (|StartsWithCurrentCulture|_|) = (|StringStartsWith|_|) StringComparison.CurrentCulture
[<return: Struct>]
let (|StartsWithCurrentCultureIgnoreCase|_|) = (|StringStartsWith|_|) StringComparison.CurrentCultureIgnoreCase
[<return: Struct>]
let (|StartsWithInvariantCulture|_|) = (|StringStartsWith|_|) StringComparison.InvariantCulture
[<return: Struct>]
let (|StartsWithInvariantCultureIgnoreCase|_|) = (|StringStartsWith|_|) StringComparison.InvariantCultureIgnoreCase
[<return: Struct>]
let (|StartsWithOrdinal|_|) = (|StringStartsWith|_|) StringComparison.Ordinal
[<return: Struct>]
let (|StartsWithOrdinalIgnoreCase|_|) = (|StringStartsWith|_|) StringComparison.OrdinalIgnoreCase
[<return: Struct>]
let (|StringEndsWith|_|) (comparisonType: StringComparison) (value: string) (s: string) =
if s.EndsWith(value, comparisonType) then ValueSome () else ValueNone
[<return: Struct>]
let (|EndsWithCurrentCulture|_|) = (|StringEndsWith|_|) StringComparison.CurrentCulture
[<return: Struct>]
let (|EndsWithCurrentCultureIgnoreCase|_|) = (|StringEndsWith|_|) StringComparison.CurrentCultureIgnoreCase
[<return: Struct>]
let (|EndsWithInvariantCulture|_|) = (|StringEndsWith|_|) StringComparison.InvariantCulture
[<return: Struct>]
let (|EndsWithInvariantCultureIgnoreCase|_|) = (|StringEndsWith|_|) StringComparison.InvariantCultureIgnoreCase
[<return: Struct>]
let (|EndsWithOrdinal|_|) = (|StringEndsWith|_|) StringComparison.Ordinal
[<return: Struct>]
let (|EndsWithOrdinalIgnoreCase|_|) = (|StringEndsWith|_|) StringComparison.OrdinalIgnoreCase
[<return: Struct>]
let (|ParseRegexWithOptions|_|) options (pattern: string) (s: string) =
match Regex.Match(s, pattern, options) with
| m when m.Success -> List.tail [ for x in m.Groups -> x.Value ] |> ValueSome
| _ -> ValueNone
[<return: Struct>]
let (|ParseRegex|_|) = (|ParseRegexWithOptions|_|) RegexOptions.None
[<return: Struct>]
let (|ParseCompiledRegex|_|) = (|ParseRegexWithOptions|_|) RegexOptions.Compiled
// Composable options with bitwise mapping
[<return: Struct>]
let (|ParseSpecialRegex|_|) = RegexOptions.IgnoreCase &&& RegexOptions.Compiled |> (|ParseRegexWithOptions|_|)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment