DarkMatter in Cyberspace
  • Home
  • Categories
  • Tags
  • Archives

F# Notes


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.



Published

Feb 14, 2019

Last Updated

Apr 18, 2019

Category

Tech

Tags

  • f# 1

Contact

  • Powered by Pelican. Theme: Elegant by Talha Mansoor