On Windows 10
Option 1: based on Visual Studio (recommended)
Console REPL
安装 Visual Studio Community 2017 后在 [Windows 开始] 中启动
"Developer Command Prompt for VS 2017"(或者在开始中输入 dev
)。
在启动的命令行环境里执行 fsi
进入 F# interpreter,
包含语法高亮和 tabcompletion,执行 #help;;
打印帮助文档,
#load
加载脚本 (for example: #load "hellowrold.fsx";;
,
note that the double quotes of the script file can't be omitted),
#r
加载动态链接库,类似于 Python 的 import
。
执行 fsc <target-file>.fs
运行 F# compiler 编译源码。
Editor-REPL
安装 VS 后,其中的组件 Visual Studio Build Tools 配合 VS Code 的 F# 插件 Ionide-fsharp 可以实现比较好的
editor-repl 工作流,Alt-Enter
执行当前行代码,editor 对代码的自动补全支持做得不错。
Full IDE
Visual Studio Community 2017 菜单 [View -> Other Windows -> F# Interactive] 启动 F# REPL,
但没有 autocompletion 和语法高亮,可以创建一个 F# 脚本,
然后通过快捷键 Alt-Enter
发送到 REPL 里执行,但 editor 里没有语法高亮和自动补全。
Note: 貌似不能单独安装 Visual Studio Build Tools 和 Developer Command Prompt for VS 2017, 只能把 3GB+ 的 VS 2017 全装上,IDE, C# 和 VB 都是强行赠送,百度和360估计都是跟 MS 学的。
Option 2: based on .NET SDK
安装体积比 VS 小很多,但功能有限,没有 REPL。
Download and install .NET SDK (dotnet-sdk-2.2.104-win-gs-x64.exe, 147MB) on Windows 10. Run the following commands:
> dotnet new console -lang F# -o myApp
> cd myApp
> cat Program.fs
open System
[<EntryPoint>]
let main argv =
printfn "Hello World from F#!"
0 // return an integer exit code
> dotnet run
On Ubuntu 16.04
Install and hellowrold:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
sudo apt install apt-transport-https
echo "deb https://download.mono-project.com/repo/ubuntu stable-xenial main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
sudo apt update
sudo apt-get update
sudo apt-get install fsharp
cat << EOF > hw.fsx
printfn "Hello world"
EOF
fsharpi hw.fsx # run script
fsharpc hw.fsx # compile to binary
./hw.exe # run binary
Vim Plugins
Add Plug 'fsharp/vim-fsharp', { 'for': 'fsharp', 'do': 'make fsautocomplete' }
into $MYVIMRC.
See vim-fsharp for details.
Namespace and Module
Default Module
When omitted, the module name is the file name. You can access the variables with or without namespace prefix:
$ cat Hw.fsx
type Person = {First: string; Last: string}
let aPerson = {First="Charlie"; Last="Adams"}
let first = aPerson.First
let last = aPerson.Last
$ fsharpi
> #load "Hw.fsx";;
[Loading /home/leo/Documents/temp/FSharpEx/Hw.fsx]
namespace FSI_0002 // this namespace is created by REPL
type Person =
{First: string;
Last: string;}
val aPerson : Person
val first : string
val last : string
> FSI_0002.Hw.first;;
val it : string = "Charlie"
> Hw.first;; // namespace name can be omitted
val it : string = "Charlie"
Note that if the initial of the file name is in lower case, the module name will be convert to that with an upper case initial.
For example:
$ cat mymod.fsx
type CustomerId = CustomerId of int
let customerId = CustomerId 42
$ fsi
> #load "mymod.fsx";;
> Mymod.customerId;;
val it : Chapter5.CustomerId = CustomerId 42
Note here you must to use Mymod
instead of mymod
to reference the variable.
Top-level Module
You can specify the name of a top-level module explicitly:
$ cat Hw2.fsx
module Hwo
type Person = {First: string; Last: string}
let aPerson = {First="Bob"; Last="Betty"}
let first = aPerson.First
let last = aPerson.Last
$ fsharpi
> #load "Hw2.fsx";;
[Loading /home/leo/Documents/temp/FSharpEx/Hw2.fsx]
namespace FSI_0002
type Person =
{First: string;
Last: string;}
val aPerson : Person
val first : string
val last : string
> Hwo.first;;
val it : string = "Bob"
> FSI_0002.Hwo.first;;
val it : string = "Bob"
Named Namespace & Local Module
You can defina a namespace explicitly, then some local modules:
$ cat Hw3.fsx
namespace MyNS
module Hwo =
type Person = {First: string; Last: string}
let aPerson = {First="Charlie"; Last="Chad"}
let first = aPerson.First
let last = aPerson.Last
$ fsharpi
> #load "Hw3.fsx";;
[Loading /home/leo/Documents/temp/FSharpEx/Hw3.fsx]
namespace FSI_0002.MyNS // notice the namespace hierarchy
type Person =
{First: string;
Last: string;}
val aPerson : Person
val first : string
val last : string
> MyNS.Hwo.first;;
val it : string = "Charlie"
> FSI_0002.MyNS.Hwo.last;;
val it : string = "Chad"
According to Is there any difference between top-level modules and local modules?, Hw3.fsx is equivalent to:
module MyNS.Hwo
type Person = {First: string; Last: string}
let aPerson = {First="Charlie"; Last="Chad"}
let first = aPerson.First
let last = aPerson.Last
So you can always use top-level module instead of namespace.
Using Other Scripts
You can load other F# scripts via #load
:
$ cat Hw4.fsx
namespace MyNS
module Hw4 =
type Person = {First: string; Last: string}
let aPerson = {First="Charlie"; Last="Chad"}
let first = aPerson.First
let last = aPerson.Last
#load "Hw2.fsx"
module App =
let names = [Hw3.first; Hwo.first]
$ fsharpi
> #load "Hw4.fsx";;
[Loading /home/leo/Documents/temp/FSharpEx/Hw2.fsx
Loading /home/leo/Documents/temp/FSharpEx/Hw4.fsx]
namespace FSI_0002
type Person =
{First: string;
Last: string;}
val aPerson : Person
val first : string
val last : string
namespace FSI_0002.MyNS
type Person =
{First: string;
Last: string;}
val aPerson : Person
val first : string
val last : string
val names : string list
> MyNS.App.names;;
val it : string list = ["Charlie"; "Bob"]
See Modules in F# Guide > F# Language Reference for details.
By conventions, namespace and module use both PascalCase. See F# code formatting guidelines > Naming conventions for details.
Backgrounds and Rationale
fsharpc
and fsharpi
are open source, cross-platform compiler and interpreter for
F#.
They are developed by F# Software Foundation.
and dependent on Mono,
a free and open-source project led by
Xamarin,
a Microsoft-owned San Francisco-based software company.
.NET Core (free and open-source) has F# compiler, too.
It seems more Visual-Studio style and project oriented (see dotnet run
above).
However it also provides an interpreter fsi.exe.
My plan is using .net platform on Windows and Mono on Linux.