Skip to content
AgileLogics
6 min read

Strings

Prerequisites: Data types

F# strings are .NET strings: immutable sequences of UTF-16 characters.

let first = "Grace"
let last = "Hopper"

let full = first + " " + last
printfn "%s" full
printfn "%d" full.Length
printfn "%c" full[0]
printfn "%s" full[0..4]
printfn "%s" (full.ToUpper())
Grace Hopper
12
G
Grace
GRACE HOPPER
  • + joins strings; .Length is the number of characters.
  • s[i] gets a character (zero-based) and s[a..b] a slice (both ends inclusive).

Interpolated strings

let item = "coffee"
let price = 3.5
let qty = 3

printfn $"{qty} x {item} = {price * float qty}"
printfn $"Total: {price * float qty:F2}"
printfn $"Typed: %d{qty} and %s{item}"
printfn $"""Quotes inside: {"nested"}"""
3 x coffee = 10.5
Total: 10.50
Typed: 3 and coffee
Quotes inside: nested

Inside $"...", any expression goes in braces, optionally followed by a .NET format (:F2 means two decimal places). Putting %d before a hole makes the compiler check its type. Triple-quoted strings ("""...""") can contain double quotes.

Escapes, verbatim, and multi-line strings

printfn "Tab:\tNew line follows\nDone"
printfn "%s" @"C:\Users\ada\notes.txt"
let poem = """Roses are red,
F# is neat."""
printfn "%s" poem
Tab:	New line follows
Done
C:\Users\ada\notes.txt
Roses are red,
F# is neat.

@"..." is a verbatim string — backslashes are literal, which is convenient for Windows paths and regular expressions.

Common string functions

let text = "  The quick brown fox  "

printfn "[%s]" (text.Trim())
printfn "%b" (text.Contains "quick")
printfn "%s" (text.Trim().Replace("quick", "slow"))
printfn "%A" (text.Trim().Split ' ')
printfn "%s" (String.concat ", " ["a"; "b"; "c"])
printfn "%d" (String.length "hello")
printfn "%s" (String.replicate 3 "ab")
printfn "%b" ("abc".StartsWith "ab")
[The quick brown fox]
true
The slow brown fox
[|"The"; "quick"; "brown"; "fox"|]
a, b, c
5
ababab
true

You'll use both .NET methods (.Trim(), .Split, .Replace) and the F# String module (String.concat, String.length, String.replicate). A method that takes a single argument can be called without parentheses: text.Contains "quick".

sprintf

sprintf works like printfn but returns the string instead of printing it:

let label = sprintf "%-8s|%5d|" "apples" 42
printfn "%s" label
printfn "%s" (sprintf "%05.1f" 3.14159)
apples  |   42|
003.1

%-8s pads to 8 characters, left-aligned; %5d right-aligns in 5; %05.1f pads with zeros.

Practice

Given let name = " ada lovelace ", print the name trimmed and in upper case, followed by its length in parentheses — using an interpolated string.

Show solution
let name = "  ada lovelace  "
let clean = name.Trim().ToUpper()
printfn $"{clean} ({clean.Length})"
ADA LOVELACE (12)