Dive C1.01.3
F# Interactive
Type an expression, end it with two semicolons, and read the answer.
FSI — F# Interactive — is the language's REPL: a read-eval-print loop where
you enter an expression, FSI evaluates it, and prints the value and its type. Start it from a terminal with
dotnet fsi. An entry is terminated with ;;, which tells FSI
to evaluate what came before; the result is printed as val it : <type> =
<value>, where it names the last unnamed result. FSI is where every
claim in this module can be confirmed in seconds, and it is how F# code is explored before it goes into a
file.
Read, evaluate, print
FSI runs a cycle: it reads an entry, evaluates it,
prints the result, and loops. The ;; terminator is the signal
to evaluate — it lets an entry span several lines, so a multi-line definition is sent only when
;; closes it. An expression with no name binds to it:
after 1 + 1;; prints val it : int = 2, the name
it holds 2 for the next entry.
A binding prints its own name and type instead. let greet name = printfn "Hello, %s"
name;; prints val greet : string -> unit — the
%s format specifier requires a string, and
printfn returns unit. Calling it,
greet "F#";;, prints the line Hello, F# as an effect and
then val it : unit = () as the result.
- start FSI
dotnet fsiopens the interactive session.- terminator
;;ends an entry and triggers evaluation.- it
- names the last unnamed result, available in the next entry.
- val name : type
- the form FSI prints — a binding's name (or
it) and its type. - run a script
dotnet fsi script.fsxexecutes an.fsxfile.
The printfn format specifiers are typed: %d
for an integer, %s for a string, %f for a float,
%b for a bool, and %A for any value (it prints structured
data such as lists and tuples).
Directives and scripts
Beyond expressions, FSI takes directives — instructions that start with
# and configure the session rather than compute a value. They load code and
references, turn on timing, and control the session.
Scripts are .fsx files: ordinary F# that FSI can run top to bottom. A script can
be loaded into a running session with #load, or executed in one shot from the
terminal with dotnet fsi script.fsx. A package is pulled in with
#r "nuget: <Package>", which fetches it from NuGet and references it, or a
local assembly with #r "<path>.dll".
#load "file.fsx" // load and run another script into the session #r "nuget: FSharp.Data" // reference a package from NuGet #r "bin/MyLib.dll" // reference a local assembly #time "on" // print elapsed time + GC for each entry #help // list the available directives #quit // leave the session
Expressions compute; directives configure. Together they make FSI a workbench — load a script, reference a library, time a call, all without leaving the loop.
A session, one entry at a time
The transcript below is a real FSI session, replayed one entry at a time. Each step appends the input you
would type and the exact line FSI prints back. The whole transcript is shown by default; the controls
replay it entry by entry. Every line was captured from dotnet fsi.
The read-eval-print loop · step through a session
> 1 + 1;;
val it : int = 2
> let greet name = printfn "Hello, %s" name;;
val greet : string -> unit
> greet "F#";;
Hello, F#
val it : unit = ()
> [1..1000] |> List.sum;;
val it : int = 500500
> #time "on";;
--> Timing now on
The loop is the whole tool: read an entry, evaluate it, print the value and its type. Repeat — and reach for it to confirm anything F# can compute.
The idea
A read-eval-print loop turns the language into a workbench: ask a question, get the typed answer at once.
F# today
dotnet fsi starts the loop; [1..1000] |> List.sum;;
returns val it : int = 500500 on the spot.
The floor is laid
Three dives complete the foundation. The primitive types name what a value can be and how to write it; inference gives every binding a type from its use; and FSI is the loop that prints both back, so any claim is one entry away from confirmation. With values, types, and the REPL in hand, the rest of the chapter builds upward — bindings and scope, functions and the pipeline, records and unions, pattern matching.
References
Sources
- Microsoft — F# documentation — F# Interactive, scripts, and the
printfformat specifiers. - The F# Software Foundation — FSI and the F# tooling.
- FSharp.Core API documentation —
List.sumand the library functions used in the session.
Related in this course
- C1.01.1 — Primitive types & literals — the values FSI prints.
- C1.01 — Values, types & FSI — the module hub and its three dives.
- Elixir — Values — the same exploration in IEx, the BEAM's REPL.