F# Module 1 – Start here: F# for .NET developers
Install .NET and run F# Interactive
Install the .NET SDK that carries F#, pin it for a folder with global.json, run dotnet fsi as a REPL and a script runner, and pull NuGet packages into scripts.
What you will learn
- Install the .NET SDK, confirm its F# compiler version and pin the SDK for a folder with global.json
- Use dotnet fsi as a REPL and as a script runner, with ;; and the
- Add NuGet packages to scripts with exact versions and explain what happens on the first run
- Set up an editor, VS Code with Ionide, Visual Studio or Rider, for F# scripts and projects
Before you start
What you’ll learn · Before you start
What you will learn
- Install the .NET SDK, confirm its F# compiler version and pin the SDK for a folder with global.json
- Use dotnet fsi as a REPL and as a script runner, with ;; and the
- Add NuGet packages to scripts with exact versions and explain what happens on the first run
- Set up an editor, VS Code with Ionide, Visual Studio or Rider, for F# scripts and projects
Before you start
On this page
Installing F# means installing one thing, the .NET SDK: The kit you install to build .NET code: the dotnet command, MSBuild, NuGet, the C# and F# compilers, F# Interactive and a .NET runtime. Without it, dotnet fsi and dotnet build cannot run.: SDK 10.0.401 carries the F# compiler, F# Interactive: The REPL and script runner of the .NET SDK, started with dotnet fsi. At the prompt it compiles and runs each entry that ends with ;; and answers with the name, type and value. and a copy of FSharp.Core 10.1.401. On the computer that recorded this lesson, a one-line script then took 2.5 to 3.6 seconds from the command to the end of its output, nearly all of it starting .NET and compiling the script: a cost that shapes how you use scripts.
This lesson installs and checks the SDK, pins it for a folder, uses F# Interactive both as a prompt you type at and as a script runner, pulls a NuGet package into a script with an exact version, and sets up an editor.
The .NET SDK is the only thing to install
Microsoft’s install page for F# offers three routes. On a computer where you build from the command line or with VS Code, install the .NET SDK from Microsoft’s download page or your platform’s package manager, as the .NET install guides for Windows, macOS and Linux describe. With Visual Studio, F# comes with the ASP.NET and web development workload. On a build server, the page says, the .NET SDK has everything you need. Install the .NET 10 SDK: .NET 10 is the long-term support release this track uses.
Then check what you got. These are the checks on the recording computer, in a folder whose global.json pins SDK
10.0.401 (DOTNET_ROOT is the folder the SDK is installed in):
from session import run
# The checks after installing the .NET SDK: the SDK dotnet picks in this folder, every SDK it could pick, the F#
# Interactive inside it, and the F# files the SDK folder holds (DOTNET_ROOT is the folder the SDK is installed in).
run("""
dotnet --version
dotnet --list-sdks
dotnet fsi --help | head -n 1
ls "$DOTNET_ROOT/sdk/10.0.401/FSharp" | grep -E '^(fsc|fsi|FSharp[.]Core)[.]dll$'
ls "$DOTNET_ROOT/sdk/10.0.401/FSharp/library-packs"
""") Output
$ dotnet --version 10.0.401 $ dotnet --list-sdks 10.0.401 […/dotnet-root/sdk] $ dotnet fsi --help | head -n 1 Microsoft (R) F# Interactive version 15.2.401.0 for F# 10.0 $ ls "$DOTNET_ROOT/sdk/10.0.401/FSharp" | grep -E '^(fsc|fsi|FSharp[.]Core)[.]dll$' fsc.dll FSharp.Core.dll fsi.dll $ ls "$DOTNET_ROOT/sdk/10.0.401/FSharp/library-packs" FSharp.Core.10.1.401.nupkg
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 check_session.py
dotnet --version prints the SDK that dotnet picks in this folder and --list-sdks every SDK installed. The first line
of dotnet fsi --help names F# Interactive and the language it compiles, F# 10.0. The last two commands show that F#
lives inside the SDK folder: fsc.dll is the compiler that builds projects, fsi.dll is F# Interactive, and
library-packs holds the FSharp.Core 10.1.401 package, so a new F# project finds FSharp.Core without downloading it.
Installing only the runtime
Wrong: installing the .NET runtime alone, which can run built programs but has no compiler. Right: install the SDK,
which includes a runtime as well. Without an SDK, dotnet fsi and dotnet build have nothing to run, because both
F# Interactive and the compiler are part of the SDK.
global.json pins the SDK for a folder, scripts included
Several SDKs can be installed side by side, and by default every dotnet command uses the newest one. A
global.json: A JSON file that pins the .NET SDK for its folder and every folder below it. dotnet looks for one in the current folder and each parent, and its rollForward value says how strictly the version must match. file chooses another for its folder and every folder below it: dotnet
looks for one in the current folder, then in each parent, and the first it finds decides. The F# 6 notes add that
dotnet fsi follows it too, so a script is checked and run by the SDK the folder pins. This session writes one with
dotnet new globaljson, then pins a folder to an SDK that is not installed:
from session import run
# global.json pins the SDK for a folder and every folder below it, for dotnet fsi as well as for builds.
# mywork pins the installed SDK; pinned-ahead asks for 10.0.500, which is not installed here.
run("""
mkdir mywork pinned-ahead
cd mywork
dotnet new globaljson --sdk-version 10.0.401 --roll-forward latestPatch
cat global.json
dotnet --version
cd ../pinned-ahead
dotnet new globaljson --sdk-version 10.0.500 --roll-forward disable
!dotnet fsi --help
""", terminal=True) Output
$ mkdir mywork pinned-ahead
$ cd mywork
$ dotnet new globaljson --sdk-version 10.0.401 --roll-forward latestPatch
The template "global.json file" was created successfully.
$ cat global.json
{
"sdk": {
"rollForward": "latestPatch",
"version": "10.0.401"
}
}
$ dotnet --version
10.0.401
$ cd ../pinned-ahead
$ dotnet new globaljson --sdk-version 10.0.500 --roll-forward disable
The template "global.json file" was created successfully.
$ dotnet fsi --help
The command could not be loaded, possibly because:
* You intended to execute a .NET application:
The application 'fsi' does not exist or is not a managed .dll or .exe.
* You intended to execute a .NET SDK command:
A compatible .NET SDK was not found.
Requested SDK version: 10.0.500
global.json file: pinned-ahead/global.json
Installed SDKs:
10.0.401 […/dotnet-root/sdk]
Install the [10.0.500] .NET SDK or update [pinned-ahead/global.json] to match an installed SDK.
Learn about SDK resolution:
https://aka.ms/dotnet/sdk-not-found
[exit status 155]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 pin_session.py
In mywork the pin is met and dotnet --version prints 10.0.401. In pinned-ahead nothing matches 10.0.500, so even
dotnet fsi --help stops with exit status 155 and names the global.json that asked for it. How strictly a pin matches
is its rollForward value:
rollForward |
With "version": "10.0.401" |
Use it for |
|---|---|---|
disable |
exactly 10.0.401, nothing else | reproducing a recorded output exactly |
latestPatch |
the newest 10.0.4xx installed, 10.0.401 or later | projects: patches apply, features stay put |
latestFeature |
the newest 10.0.xxx installed, 10.0.401 or later | projects that may take a newer feature band |
| left out | patch: 10.0.401, else the newest 10.0.4xx |
the default when a version is given |
Every examples folder of this track pins 10.0.401 with disable, so the recorded runs come from exactly that SDK. In
your own projects prefer latestPatch: Microsoft supports only the newest servicing update, and a pin that refuses
every patch also refuses its security fixes.
Key idea
One SDK carries everything F# needs, and a global.json in a folder decides which installed SDK every dotnet command there uses, dotnet fsi included.
Checkpoint
Check: What the .NET SDK holds · Pinning the SDK with global.json
F# Interactive runs an entry once you end it with two semicolons
dotnet fsi with no file starts F# Interactive, a REPL: Read, evaluate, print loop: a prompt that reads an entry, runs it, prints the result and waits for the next one, so code can be tried a line at a time.: it reads an
entry, compiles and runs it, prints the result and waits for the next. An entry ends with two semicolons, ;;; until
you type them, Enter only starts a new line of the same entry, shown after a - prompt. Here is a first session:
from session import fsi
# A first session in F# Interactive: each entry ends with ;; and the answer names every value with its type.
fsi([
"let price = 250;;",
"let total qty =\n price * qty;;",
"total 4;;",
"it + 1;;",
"let price = 300;;",
"total 4;;",
"totl 4;;",
"#quit;;",
]) Output
$ dotnet fsi Microsoft (R) F# Interactive version 15.2.401.0 for F# 10.0 Copyright (c) Microsoft Corporation. All Rights Reserved. For help type #help;; > let price = 250;; val price: int = 250 > let total qty = - price * qty;; val total: qty: int -> int > total 4;; val it: int = 1000 > it + 1;; val it: int = 1001 > let price = 300;; val price: int = 300 > total 4;; val it: int = 1000 > totl 4;; totl 4;; ^^^^ stdin(8,1): error FS0039: The value or constructor 'totl' is not defined. Maybe you want one of the following: total > #quit;;
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 repl_session.py
Every answer is a val line with a name, the type F# Interactive inferred and the value. total 4 has no name of its
own, so its value is bound to it, which the next entry used to get 1001. The typo totl stopped with error FS0039,
and the message suggested total; the session carried on, because a failed entry changes nothing. Step through the six
entries before it:
The drawing shows the whole scene; its 7 steps are listed below.
Every step as text
- An entry ends with ;;. You type let price = 250 and end it with ;;. Until the two semicolons, pressing Enter only starts a new line of the same entry, shown after a - prompt.
- Compiled, then run. F# Interactive compiles the entry as the compiler would compile a file, then runs it at once.
- The answer names the type. It answers with a val line: the name, the type it inferred and the value. price is an int.
- A function is a value too. total uses price, so it keeps the price that exists now. Its val line gives its type: it takes an int called qty and returns an int.
- An unnamed result is it. total 4 has no name, so F# Interactive binds its value to it. The next entry, it + 1, gets 1001 from it.
- A new price hides the old. let price = 300 does not change the first price. It defines a new value with the same name, which every later entry sees. This is shadowing.
- total still sees 250. total 4 is still 1000, because total was compiled with the first price. To change what total computes, define total again after the new price.
The surprise is the last answer. let price = 300 did not change price: it defined a second value with the same name,
which hides the first one from later entries. That is shadowing: Defining a new value with a name that is already in use. Later code sees the new value, while code compiled earlier keeps the value it was compiled with., and total was compiled
with the first price, so it still answers 1000.
Redefining a value and expecting old functions to follow
Wrong: let price = 300;; and then total 4;;, expecting 1200. Right: run the definition of total again after
the new price, or make price a parameter: let total price qty = price * qty.
Lines that start with # are directives to F# Interactive rather than F# code. #quit ends the session, #time
switches timing on and off, and since F# 9 #help followed by a name shows that function’s documentation:
from session import fsi
# Two directives of F# Interactive: #time measures every entry, #help shows a function's documentation.
fsi([
'#time "on";;',
"List.sum [ for i in 1L .. 1_000_000L -> i * i ];;",
'#time "off";;',
"#help List.map;;",
"#quit;;",
], args=["--nologo"], keep_times=True) Output
$ dotnet fsi --nologo > #time "on";; --> Timing now on > List.sum [ for i in 1L .. 1_000_000L -> i * i ];; Real: 00:00:00.079, CPU: 00:00:00.014, GC gen0: 0, gen1: 0, gen2: 0 val it: int64 = 333333833333500000L > #time "off";; --> Timing now off > #help List.map;; Description: Builds a new collection whose elements are the results of applying the given function to each of the elements of the collection. Remarks: This is an O(n) operation, where n is the length of the list. Parameters: - mapping: The function to transform elements from the input list. - list: The input list. Returns: The list of transformed elements. Examples: let inputs = [ "a"; "bbb"; "cc" ] inputs |> List.map (fun x -> x.Length) // Evaluates to [ 1; 3; 2 ] Full name: Microsoft.FSharp.Collections.ListModule.map Assembly: FSharp.Core.dll > #quit;;
This output changes from run to run: The times that #time reports differ from run to run and from computer to computer; the result and the documentation do not.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 directives_session.py
With timing on, every entry reports its real time, the processor time it used and how many garbage collections of each
generation ran. Summing a million squares took under a tenth of a second here, with no collection. The other
directives that matter early are #r for packages and assemblies, which the last part of this lesson uses, #load
for another script and #i for a package source.
Checkpoint
Check: Entries, it and shadowing at the prompt
A script runs from top to bottom and prints only what it prints
A script: An F# source file with the .fsx extension that dotnet fsi compiles and runs from top to bottom, with no project file. It can reference NuGet packages with #r directives. is a .fsx file that dotnet fsi script.fsx compiles and runs from top to
bottom. Arguments after the file name reach the script in fsi.CommandLineArgs, whose first element is always the
script’s own name. This one adds up the whole numbers it is given:
#!/usr/bin/env -S dotnet fsi
// tally.fsx: adds up the whole numbers given after the script's name.
let args = fsi.CommandLineArgs
printfn "Arguments: %A" args
let numbers = args[1..]
let bad = numbers |> Array.filter (fun s -> not (fst (System.Int32.TryParse s)))
if bad.Length > 0 then
eprintfn "Not a whole number: %s" (String.concat ", " bad)
exit 2
let total = numbers |> Array.sumBy int
let twice = total * 2 // a script prints only what it prints: there is no val line for this
printfn "%d numbers, total %d" numbers.Length total from session import run
# tally.fsx run as a script, with good and bad arguments, then directly through its first line (macOS and Linux).
run("""
dotnet fsi tally.fsx 12 30 8
!dotnet fsi tally.fsx 12 thirty 8
chmod +x tally.fsx
./tally.fsx 5 5
""") Output
$ dotnet fsi tally.fsx 12 30 8 Arguments: [|"tally.fsx"; "12"; "30"; "8"|] 3 numbers, total 50 $ dotnet fsi tally.fsx 12 thirty 8 Arguments: [|"tally.fsx"; "12"; "thirty"; "8"|] Not a whole number: thirty [exit status 2] $ chmod +x tally.fsx $ ./tally.fsx 5 5 Arguments: [|"./tally.fsx"; "5"; "5"|] 2 numbers, total 10
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 script_session.py
Three things differ from a session at the prompt. Nothing is echoed: let twice = total * 2 defines a value but
prints no val line, so a script shows only what it prints itself. A problem can end the script with a status of
your choosing, here exit 2 after eprintfn wrote the message to standard error, which a calling script or a build
step can test. And on macOS and Linux the first line, #!/usr/bin/env -S dotnet fsi, lets the file run as a command
once it is executable, as ./tally.fsx 5 5 did; on Windows, run dotnet fsi tally.fsx.
Each run starts .NET and F# Interactive afresh, and that start is most of the cost of a short script:
from session import run
# How long a one-line script takes from start to finish (/usr/bin/time -p prints real, user and system seconds).
run("""
/usr/bin/time -p dotnet fsi hello.fsx
/usr/bin/time -p dotnet fsi hello.fsx
""", keep_times=True) Output
$ /usr/bin/time -p dotnet fsi hello.fsx Hello from F# on .NET 10.0.12 real 3.55 user 1.19 sys 0.63 $ /usr/bin/time -p dotnet fsi hello.fsx Hello from F# on .NET 10.0.12 real 2.46 user 1.15 sys 0.32
This output changes from run to run: Start-up times differ from run to run and from computer to computer; the program's output does not.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 startup_session.py
The two runs of a one-line script took 3.6 and 2.5 seconds of real time on the recording computer, which was busy with
other work, and about 1.2 seconds of processor time each on the user line; the million squares above took under a
tenth of a second. Almost all of a short script’s time is starting the runtime and compiling the script. Keep related
work in one script rather than many tiny ones, and explore at the prompt, where the start-up is paid once.
Checkpoint
Check: Running a script
Scripts reference NuGet packages with #r, pinned to a version
A script can use any NuGet package without a project file: #r "nuget: Name, Version" at its top makes dotnet fsi
restore the package before the script runs. This session has no network, so it first shows what that means for a
package that is in no source the computer can reach. Then it packs two versions of a small library, Paise, into a
local folder, and runs scripts whose nuget.config names that folder as their only package source:
#r "nuget: Paise, 1.0.0"
printfn "Paise %s: %s" Paise.Money.version (Paise.Money.format 123456L) from session import run
# The network is off in this session. First a script whose package is in no source this computer can reach; then a
# folder of packages made here, two versions of a small library called Paise, and scripts that a nuget.config points
# at that folder.
run("""
!dotnet fsi offline/pinned.fsx
dotnet pack Paise -o feed -p:Version=1.0.0 -v q
dotnet pack Paise -o feed -p:Version=1.1.0 -v q
ls feed
cd scripts
/usr/bin/time -p dotnet fsi pinned.fsx
/usr/bin/time -p dotnet fsi pinned.fsx
ls ~/.nuget/packages/paise
dotnet fsi latest.fsx
""", keep_times=True) Output
$ dotnet fsi offline/pinned.fsx offline/pinned.fsx(1,1): error FS0999: ~/.packagemanagement/nuget/Projects/<id>/Project.fsproj : error NU1301: Unable to load the service index for source https://api.nuget.org/v3/index.json. [exit status 1] $ dotnet pack Paise -o feed -p:Version=1.0.0 -v q $ dotnet pack Paise -o feed -p:Version=1.1.0 -v q $ ls feed Paise.1.0.0.nupkg Paise.1.1.0.nupkg $ cd scripts $ /usr/bin/time -p dotnet fsi pinned.fsx Paise 1.0.0: Rs 1234.56 real 9.17 user 2.74 sys 0.87 $ /usr/bin/time -p dotnet fsi pinned.fsx Paise 1.0.0: Rs 1234.56 real 3.85 user 1.02 sys 0.27 $ ls ~/.nuget/packages/paise 1.0.0 $ dotnet fsi latest.fsx Paise 1.1.0: Rs 1234.56
This output changes from run to run: Restore and start-up times differ from run to run and from computer to computer; the steps and what the scripts print do not.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 nuget_session.py
The offline run failed before a line of the script ran, with error NU1301: the package was in no folder on the
computer and nuget.org was out of reach. With the local source, the first run of pinned.fsx restored Paise 1.0.0 and
took 9.2 seconds of real time; the second found it in ~/.nuget/packages, the
global packages folder: The folder where NuGet keeps every package version it has restored, ~/.nuget/packages by default. A later restore of the same version takes it from there instead of from a source., and took 3.9. Step through the first run, then the
second:
The drawing shows the whole scene; its 7 steps are listed below.
Every step as text
- Directives first. Before compiling anything, dotnet fsi collects the script's #r "nuget: …" lines. pinned.fsx asks for exactly Paise 1.0.0.
- A project for the packages. It writes a small project that references those packages, under .packagemanagement in your home folder. The error of the offline run names that project.
- Not there yet. On the first run Paise 1.0.0 is not in the package folder, so it must come from a package source.
- Restore. NuGet restores the package from the sources nuget.config names, here only the local feed folder, and keeps a copy in ~/.nuget/packages/paise/1.0.0. With no reachable source, the run stops here with error NU1301.
- Reference and run. Paise.dll is referenced for this run, the script compiles and prints Paise 1.0.0. The first run took 9.2 s of real time in the recorded session.
- The second run. The second run finds Paise 1.0.0 in the package folder and skips the restore, which is why it took 3.9 s instead of 9.2 s.
- Without a version. latest.fsx writes
The last command is the reason to pin. latest.fsx is the same script with #r "nuget: Paise" and no version, and
the F# Interactive reference says such a reference takes the highest version available that is not a preview. The
moment 1.1.0 existed, the same script printed Paise 1.1.0: an unpinned script can change its output with nobody
touching it. A nuget.config next to the script decides where packages may come from, which matters for build
agents without internet access; #i "nuget: <folder>" adds a source too, but the reference notes it does not accept
relative paths yet.
Packages run with your permissions
A script’s packages run with everything your account can do. Microsoft’s F# Interactive reference gives the same advice as for any package reference: only include dependencies from sources you trust. Pin the versions you checked, too, so a new release cannot slip in.
Checkpoint
Check: Package references in scripts
Three editors understand F# through the same compiler
Any editor can open a .fsx file, but these three check F# as you type, run scripts in F# Interactive and load
projects:
| Editor, and where it runs | How F# support comes | Sending code to F# Interactive |
|---|---|---|
| VS Code with Ionide: Windows, macOS, Linux | the Ionide for F# extension, a community project | select the code, then Alt+Enter |
| Visual Studio: Windows | the ASP.NET and web development workload | select the code, then Alt+Enter |
| JetBrains Rider: Windows, macOS, Linux | the F# Support plugin, bundled and on by default | select the code, then Send Selection to F# Interactive |
Microsoft’s install page for F# names Ionide as the only plugin VS Code needs, and its VS Code guide describes Ionide
as an open-source project built and maintained by members of the F# community. Whichever editor you choose, it uses
the SDK that the folder’s global.json pins, the same one dotnet fsi uses at the command line. Notebooks are no
longer an option to plan around: Polyglot Notebooks and .NET Interactive, which ran F# in notebooks, were deprecated
and their repository archived, so this track uses .fsx scripts for exploring.
Send code from a file to F# Interactive
In VS Code with Ionide, put let price = 250 and let total qty = price * qty in a new file, scratch.fsx, select
both lines and press Alt+Enter. The F# Interactive pane answers with the same val lines as the first session above;
then type total 4;; in the pane.
Checkpoint
Check: Editors for F#
Practise: installing, running and referencing
Here are questions on the SDK, global.json, the prompt, scripts, package references and editors. They arrive one by one, weakest idea first, and whichever answer you pick, the explanation of why it works or fails opens straight away:
Practice that adapts to you
Practise this lesson
12 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up (fresher to 2–5 years): what is F# Interactive, and when would you use a script instead of a project?
F# Interactive, started with dotnet fsi, is the REPL and script runner that ships in the .NET SDK. At the prompt it
compiles and runs each entry ending with ;; and prints a val line with the name, type and value; given a .fsx
file it runs the script from top to bottom and prints only what the script prints. Scripts suit exploration,
automation, data checks and one-off tasks: they need no project file, can reference NuGet packages with
#r "nuget: Name, Version", and receive arguments in fsi.CommandLineArgs. A project suits code that several files
make up, that is compiled into an assembly, tested, packaged or deployed, and code that must start fast, because a
script compiles on every run.
Two harder questions follow, about a script whose output changed by itself and about scripts on build agents without internet access:
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Mid to senior
A nightly F# script that builds a sales report printed different totals this week, although nobody changed the script or its data. It starts with #r lines for two packages, without versions. How do you investigate, and how do you stop it happening again?
-
Mid to senior
Your team's F# build scripts must run on build agents that have no internet access, and some of them reference NuGet packages with #r. What do you set up so that they work there, and how do you check it before the agents depend on it?
Key takeaways
- The .NET SDK is the one thing to install: it carries the F# compiler, F# Interactive and FSharp.Core, and
dotnet --versionanddotnet fsi --helpshow what you got. - A
global.jsondecides which installed SDK everydotnetcommand in its folder uses,dotnet fsiincluded;latestPatchsuits projects,disablereproduces a recorded output exactly. - At the prompt, an entry ends with
;;, an unnamed result becomesit, and a secondletwith the same name shadows the first while older functions keep the value they were compiled with. - A script runs from top to bottom, prints only what it prints, reads its arguments from
fsi.CommandLineArgsand can end withexit; most of a short script’s time is start-up. #r "nuget: Name, Version"restores a package into the global packages folder on the first run; pin the version, or the script changes its output whenever a newer one appears.
Terms in this lesson
- .NET SDK
- The kit you install to build .NET code: the dotnet command, MSBuild, NuGet, the C# and F# compilers, F# Interactive and a .NET runtime. Without it, dotnet fsi and dotnet build cannot run.
- F# Interactive
- The REPL and script runner of the .NET SDK, started with dotnet fsi. At the prompt it compiles and runs each entry that ends with ;; and answers with the name, type and value.
- global packages folder
- The folder where NuGet keeps every package version it has restored, ~/.nuget/packages by default. A later restore of the same version takes it from there instead of from a source.
- global.json
- A JSON file that pins the .NET SDK for its folder and every folder below it. dotnet looks for one in the current folder and each parent, and its rollForward value says how strictly the version must match.
- REPL
- Read, evaluate, print loop: a prompt that reads an entry, runs it, prints the result and waits for the next one, so code can be tried a line at a time.
- script
- An F# source file with the .fsx extension that dotnet fsi compiles and runs from top to bottom, with no project file. It can reference NuGet packages with #r directives.
- shadowing
- Defining a new value with a name that is already in use. Later code sees the new value, while code compiled earlier keeps the value it was compiled with.
References
- Install F# (Microsoft Learn)
- Download .NET 10.0 (Microsoft)
- Install .NET on macOS (Microsoft Learn)
- Install .NET on Windows (Microsoft Learn)
- Install .NET on Linux (Microsoft Learn)
- F# Interactive (dotnet) reference (Microsoft Learn)
- F# Interactive options (Microsoft Learn)
- global.json overview (Microsoft Learn)
- Select which .NET version to use (Microsoft Learn)
- What's new in F# 6: pin the SDK version of your F# scripts (Microsoft Learn)
- What's new in F# 9: extended #help directive (Microsoft Learn)
- Managing the global packages, cache and temp folders (Microsoft Learn)
- nuget.config reference (Microsoft Learn)
- NuGet error NU1301 (Microsoft Learn)
- Get started with F# in Visual Studio Code (Microsoft Learn)
- Get started with F# in Visual Studio (Microsoft Learn)
- Ionide (Ionide)
- F# in JetBrains Rider (JetBrains)
- F# Interactive in JetBrains Rider (JetBrains)
- Polyglot Notebooks and .NET Interactive deprecation notice (.NET Interactive (GitHub))
Report a problem with this lesson
Kept only in this browser. Your Learn progress