From 58aa302f49311475cce11dcbd477df217e790ea6 Mon Sep 17 00:00:00 2001 From: Joel Stålnacke Date: Fri, 13 Feb 2026 20:48:51 +0200 Subject: Initial commit --- examples/Basic/Program.fs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 examples/Basic/Program.fs (limited to 'examples/Basic/Program.fs') diff --git a/examples/Basic/Program.fs b/examples/Basic/Program.fs new file mode 100644 index 0000000..a84f96e --- /dev/null +++ b/examples/Basic/Program.fs @@ -0,0 +1,40 @@ +open FunctionalObjects + +// A record is like an interface +type Printer = { + PrintMessage : string -> unit +} + +// Let's define a printHelloWorld function which uses the Printer interface. +// +// Notice that the type annotation is not required because Printer is a record +// and F# can infer the type of the variable based on the PrintMessage field. +// +// Because this pattern uses a concrete type for the interface, no runtime +// reflection is needed and type checking happens completely at compile time. +let printHelloWorld (printer : Printer) = + printer.PrintMessage "Hello World" + +// An instance of the record is a class aka an implementation of the interface +let basePrinter : Printer = + { PrintMessage = fun s -> printfn "Message: %s" s } + +printfn "Using the base printer:" +printHelloWorld basePrinter + +// We can create a sub-class of the base printer using Object.derive +// +// Object.derive is simply +// let derive f o = f o +// so it's completely syntactic sugar +let screamingPrinter : Printer = + basePrinter + |> Object.derive (fun b -> + { b with + // We choose which methods to override + PrintMessage = + fun s -> b.PrintMessage (s.ToUpper()) }) + +// printHelloWorld doesn't have to change when we switch the Printer. +printfn "Using the screaming printer:" +printHelloWorld screamingPrinter -- cgit v1.2.3