summaryrefslogtreecommitdiff
path: root/examples/Basic
diff options
context:
space:
mode:
authorJoel Stålnacke <joel@saker.fi>2026-02-13 20:48:51 +0200
committerJoel Stålnacke <joel@saker.fi>2026-02-13 20:48:51 +0200
commit58aa302f49311475cce11dcbd477df217e790ea6 (patch)
treed61bf5a2ebcf7004ab411b555a9183b9781c0888 /examples/Basic
Initial commitHEADmaster
Diffstat (limited to 'examples/Basic')
-rw-r--r--examples/Basic/FunctionalObjects.Examples.Basic.fsproj16
-rw-r--r--examples/Basic/Program.fs40
2 files changed, 56 insertions, 0 deletions
diff --git a/examples/Basic/FunctionalObjects.Examples.Basic.fsproj b/examples/Basic/FunctionalObjects.Examples.Basic.fsproj
new file mode 100644
index 0000000..806da26
--- /dev/null
+++ b/examples/Basic/FunctionalObjects.Examples.Basic.fsproj
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net10.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="Program.fs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\FunctionalObjects\FunctionalObjects.fsproj" />
+ </ItemGroup>
+
+</Project>
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