F#是.NET平台上的函算式语言。
- What is F#
- 过
- Get Started
- Get Started
- Get started online
- 有Fable REPL和JupyterNotebook版本可用。
- Get started online
- Get Started
- F# Language Guide
- F# language reference
- Compiler Directives
- Preprocessor Directives(过)
- Compiler Directives
- Tutorials
- Tour of F#
- 文首
- 两个核心概念:算函和类型
- Executing the code online(略)
- Functions and Modules
- 算函按照模块组织
- 算函定义使用let绑定来管理名字和参数
- let绑定默认是禁变更的,如果需要其可变更,则需要指定
let mutable ...
let mutable otherNumber = 2
尔后otherNumber <- otherNumber + 1
- Numbers, Booleans, and Strings
- F#支持.NET的元初类型https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/basic-types
- 嗯,支持这些语法
let sampleNumbers = [ 0 .. 99 ]
let sampleTableOfSquares = [ for i in 0 .. 99 -> (i, i*i) ]
- Tuples
- 这个在函算式语言中经常用到。
- 可以创建struct类型元组,例如
let convertFromStructTuple (struct(a, b)) = struct(b, a)
,主要是和C#7/VB15互操作用
- Pipelines
- 管道运算符
|>
,可以将算函以管道的形式串起来
- 管道运算符
- Lists, Arrays, and Sequences
- 链对、排阵、序列是主要合集类型
- 链对是排序的、禁变更的同类型元素合集
- 形式为
[1;2;3]
,分号可用换行符代替,元素可以通过1..100
形式展开。 - 更高级的操作:
/// 'yield' is used for on-demand evaluation. More on this later in Sequences. let daysList = [ for month in 1 .. 12 do for day in 1 .. System.DateTime.DaysInMonth(2017, month) do yield System.DateTime(2017, month, day) ]
- 形式为
- 排阵是固定尺寸,可变更的、同类型元素合集
- 形式为
let array3 = [| 1 .. 1000 |]
let evenNumbers = Array.init 1001 (fun n -> n * 2)
- 形式为
- 序列是逻辑上的同类型元素的有序队列,支持惰性计算
- 形式为
let seq1 = Seq.empty
let seq2 = seq { yield "hello"; yield "world"; yield "and"; yield "hello"; yield "world"; yield "again" }
let evenNumbers = Seq.init 1001 (fun n -> n * 2)
- 形式为
- Recursive Functions
- 虽然F#支持命令式的循环,但是更推荐使用递归
- 看见
let rec
和match
了 - 完整支持Tail Call Optimization,太好了
- Record and Discriminated Union Types
- Record和联合类型是两个基础的数据类型,这俩有structural equality semantics,直接对比就行
- Record(录格)是带名字量值的聚合,有点类似于POCO,或者Java的POJO
- 形如:
type ContactCard = {Name : string}
- 可以把记录表示为struct,只要在前头加上
[<Struct>]
- 形如:
- Discriminated Unions (DUs)是一些可以表示为多种类型的量值
- 形如
type Suit = | Hearts | Clubs | Diamonds |Spades
- 形如
fs type Rank = /// Represents the rank of cards 2 .. 10 | Value of int | Ace | King | Queen
- DUs可以化为Single-Case Discriminated Unions
- 形如
type Address = Address of string
- 需要显示unwrap:
let unwrapAddress (Address a) = a
- 形如
- DUs可以支持递归定义
- 形如
type BST<'T> = | Empty | Node of value:'T * left: BST<'T> * right: BST<'T>
- 形如
- 形如
- Pattern Matching
- 此特性在操作F#类型的时候确保正确性,编译器会做很多检查
- 此举叫做Exhaustive Pattern Matching
- (剩余过)
- Options
- 表示有或无(剩余略)
- Units of Measure
- 可以给数字加上测量单位
- Object Programming
- 拥有完整的客件编程支持:class, interface, abstract class, inheritance等等
- Which Types to Use
- Tuple适合用于算函返回多个值,或临时聚合多个值
- Record比Tuple进一步,可以给成员取名字,但还是比较low-ceremony,而且structural equality让比较操作很简单
- Discriminated Union主要是和模式匹配配合使用
- Class(卡类?)用途比较广,主要给数据堆模型比较方便
- 文首
- Functional programming concepts
- 过
- Asynchronous programming
- 文首
- 异步编程的主要用途
- 增加服务端进程的并发处理能力
- 增加UI或者主线程的并发处理能力
-
增加并发度,往往意味着需要等待更长时间才能得到运算结果
- 异步编程的主要用途
- Asynchrony defined
- 过
- 文首
- Using functions
-
okay, 似乎是为函算式编程特别准备的一章。
-
- Tour of F#
- F# tools
- F# Development Tools
- Community Tools
- Fantomas,代码格式化工具
- FSharpLint,代码检查工具
- FAKE,建构自动化工具
- 其他参考https://fsharp.org/community/projects/
- Community Tools
- F# Interactive
- 文首
- dotnet fsi是其交互式工具
- Executing code directly in F# Interactive
-
显然不如LinqPad好用啊
-
- Scripting with F#
- dotnet fsi可以执行脚本,脚本文件一般命名为fsx结尾
- Referencing packages in F# Interactive
#r "nuget: Newtonsoft.Json"
- Specifying a package source
#i "nuget: https://my-remote-package-source/index.json"
#i """nuget: C:\path\to\my\local\source"""
- Referencing assemblies on disk with F# interactive
#r "path/to/MyAssembly.dll"
- Loading other scripts
#load "Script1.fsx"
- Using the fsi object in F# code
let args = fsi.CommandLineArgs
- F# Interactive directive reference
- 过
- Interactive and compiled preprocessor directives
#if INTERACTIVE
- Using F# Interactive in Visual Studio
- 略
- 文首
- F# notebooks
- 可以在Jupyter、VSCode、Visual Studio上使用.NET Interactive F# notebooks
- F# for JavaScript
- F#可以作为JS代码运行,工具链是社区提供的,且开源
- Fable
- 将F#转编译成JS,可以支持React
- WebSharper
- 提供全栈式的函算式的响应性web编程
- F# Development Tools
- F# style guid
- F# for machine learning
- 记
F# language guide
- Overview
- Organizing F# Code
- (其余略)
- Literals
- (过)
- Functions
- Functions
- Syntax
-
// Non-recursive function definition. let [inline] function-name parameter-list [ : return-type ] = function-body // Recursive function definition. let rec function-name parameter-list = recursive-function-body
-
- Remarks(略)
- Scope(略)
- Parameters(略)
- Function Bodies(略)
- Return Values
- 多参数加返回值形式:
let cylinderVolume (radius : float) (length : float) : float
- 多参数加返回值形式:
- Calling a Function
- 形如:
let vol = cylinderVolume 2.0 3.0
- 形如:
- Partial Application of Arguments(略)
- Recursive Functions(略)
- Function Values(略)
- Lambda Expressions
- 形如:
fun x -> x + 1
- 形如:
- Pipelines
- 形如:
let result = 100 |> function1 |> function2
- 管道操作符的定义:
let (|>) x f = f x
- 形如:
- Function composition
- 形如:
let h = function1 >> function2
- 形如:
- Overloading Functions
- 可以重载类型的方法,但是补能重载一个算函
- Syntax
- Recursive Functions: The rec Keyword
- Syntax
- 相互递归的写法:
// Mutually recursive functions: let rec function1-name parameter-list = function1-body and function2-name parameter-list = function2-body ...
- 相互递归的写法:
- Remarks
- 类型成员默认在其类型内是相互递归的,不需要写rec
- Tail recursion(略)
- Mutually Recursive Functions(略)
- Recursive values
- 有点意思:
let rec nameDoubles = nameof nameDoubles + nameof nameDoubles
- 有点意思:
- Syntax
- Inline Functions
- (未读)
- Function Expressions
- (未读)
- Functions
- Loops and conditionals
- for..in loops
- (过)
- for..in loops
- Pattern matching
- Overview
- Remarks
- 语法
match expression with | pattern [ when condition ] -> result-expression ...
- pattern的种类可以好多
- 语法
- Remarks
- Active Patterns
- 可以定义具名的分区,用于进一步划分输入数据,有点类似于discriminated union。
- Syntax(过)
- Remarks
- 形如:
let (|Even|Odd|) input = if input % 2 = 0 then Even else Odd
- 可以有多至7个分区
||
叫做banana clips,用此创建的函数叫做active recognizer
- 形如:
- Partial Active Patterns
- 通配符
_
,空匹配None
,有匹配Some
- 模式之间不必是互斥的
- 通配符
- Parameterized Active Patterns
- 总是至少带一个参数用于码取(match),其实可以带更多参数
- 也可以用于let匹配,形如
let greet (Default "random citizen" name) = ...
- 只有单案例的active pattern可以带更多参数
- Struct Representations for Partial Active Patterns(略)
- Overview
- Types and inference
- Overview
- (过)
- Type Abbreviations
- Syntax
type [accessibility-modifier] type-abbreviation = type-name
- Remarks
- 类型缩写的默认访问级别是公开的
- 可以包含泛型参数,如
type Transform<'a> = 'a -> 'a
- Syntax
- Casting and Conversions
- Unit Type
()
- Remarks(略)
- Overview
- Records and unions
- Discriminated Unions
- 文首
- 简单说DU可以将多个不同类型合为一个,也就是给heterogeneous数据的处理提供支持
- 要知道,F#中的List,以及其他大多数类型,其实是homegeneous的
- Syntax(过)
- Remarks
- 可以光指定case名字,这样一来,表现得像个枚举
- case的域属可以匿名
- 可以用case构造此类型,构造的时候域属顺序可以打乱
- 比如option类型是这么定义的
option是Option的别名
type Option<'a> = | Some of 'a | None
- case可以用做码取
- 码取的时候可以指定域属
let getShapeWidth shape = match shape with | Rectangle(width = w) -> w
- 通过在DU上设置 RequireQualifiedAccess属性,可以强制case必须加上DU名
- Unwrapping Discriminated Unions
- 可以直接使用let来反解:
let ([UnionCaseIdentifier] [values]) = [UnionValue]
- 可以直接在算函参数上指定
- 开可以声明单case的:
type ShaderProgram = | ShaderProgram of id:int
- 可以直接使用let来反解:
- Struct Discriminated Unions
- 可以将DU表示为struct,只要加上
|<Struct>|
属性,这样就变成了量值类型了 - 但是存在一些考量
- 会被像量值一样拷贝
- 无法定义使用递归类型
- 多case情况下,必须提供独特的case名字
- 可以将DU表示为struct,只要加上
- Using Discriminated Unions Instead of Object Hierarchies
- 可以作为简单的客件层次的替代
- 使用码取,而不是虚算函机制来按具体case操作
- Using Discriminated Unions for Tree Data Structures
- 介绍了二叉树的例子
- 还有一个编程语言表达式的例子
- Members
- 可以定义member,以及可以实现接口
- Common attributes
- 有下面几种属性可以使用
[<RequireQualifiedAccess>]
[<NoEquality>]
[<NoComparison>]
[<Struct>]
- 有下面几种属性可以使用
- 文首
- Discriminated Unions
- Object programming
- Classes (F#)
- (未读)
- Interfaces
- Syntax(过)
- Remarks
- 类似于标类的定义,但不提供成员,也不支持默认实现
- 例子:
type ISprintable = abstract member Print : format:string -> unit
- 可以通过客件表达式,或通过标类类型来实现抽象方法
- 关键字interface和end是可选的
- 多个参数可以用两种方式表示
- F#风格:
abstract Add: x: int -> y: int -> int
- .NET风格:
abstract Add: x: int * y: int -> int
- F#风格:
- Implementing Interfaces by Using Class Types
- 会被自动继承
- 示例:
interface IPrintable with member this.Print() = printfn "%d %f" x y
- Calling Interface Methods
- 只能通过接口来调用,形如:
(x1 :> IPrintable).Print()
- 一个替代办法是定义一个相衬的member:
member this.Print() = (this :> IPrintable).Print()
- 只能通过接口来调用,形如:
- Implementing Interfaces by Using Object Expressions
- 示例:
let makePrintable(x: int, y: float) = { new IPrintable with member this.Print() = printfn "%d %f" x y }
- 示例:
- Interface Inheritance
- 示例:
type Interface3 = inherit Interface1 inherit Interface2 abstract member Method3 : int -> int
- 示例:
- Implementing interfaces with default implementations(略)
- Implementing the same interface at different generic instantiations(略)
- Members
- Remarks【注解】
- F#中的许多客件支持使用
member
关键字指定特性 - members默认是公开的,单可以指定为private或者internal
- 私有域属以及do绑定只在标类中使用,并不是真正的成员
- F#中的许多客件支持使用
- Remarks【注解】
- Methods
- Syntax(过)
- Remarks
- 可以指定属性或者将其inline
- 方法间默认为rec
- Instance Methods
- Static Methods
- Abstract and Virtual Methods
- Overloaded Methods
- Optional Arguments
- Example: Properties and Methods
- Inheritance
- Inheritance is used to model the “is-a” relationship, or subtyping, in object-oriented programming.
- Specifying Inheritance Relationships
- 不出意外,使用inherit关键字
- Classes (F#)
- Tuples, options, results
- Tuples
- A tuple is a grouping of unnamed but ordered values, possibly of different types. Tuples can either be reference types or structs.
- Options
- Remarks
- 形如:
let keepIfPositive (a : int) = if a > 0 then Some(a) else None
- 形如:
- Remarks
- Value Options
- 在满足以下情况的时候使用
- 适合使用Option
- 同时适合使用struct
- 在满足以下情况的时候使用
- Tuples
- Collections
- Lists
- A list in F# is an ordered, immutable series of elements of the same type. To perform basic operations on lists, use the functions in the List module.
- Creating and Initializing Lists
- 语法:
let list123 = [1;2;3]
,也可以用分行代替分号
- 语法:
- Operators for Working with Lists
- 连结操作符是
::
,例子:let list2 = 100 :: list1
- 串并操作符是
@
,例子:let list3 = list1 @ list2
- 连结操作符是
- Properties
- Using Lists
- Sequences
- Sequence Expressions
- The yield! keyword
- Examples
- Lists
- Reflection
- Attributes
- Syntax
- 形如:
[<target:attribute-name(arguments)>]
- 形如:
- Remarks
- target是可选的
- 一个例子
[<DllImport("kernel32", SetLastError=true)>] extern bool CloseHandle(nativeint handle)
- 属性不可以用于let绑定之上
- 对于属性目标
assembly
和module
,可应用于顶层的do绑定之上 - 需要属性标类具有
System.AttributeUsageAttribute
类型的属性 - 表格中列出了属性目标:assembly, module, return, field, property, param, type
- Syntax
- Code quotations
- 用于生成和操作F#代码表达式(厉害了)
- nameof
- Syntax
nameof symbol
nameof<'TGeneric>
- Remarks
- 可以用于检查参数:
invalidArg (nameof month) ($"Value passed in was %d{month}.")
- 基本上可以用于任意构造
- 可以用于检查参数:
- Nameof on operators
- 例如
nameof op_Addition // "op_Addition"
- 例如
- Nameof on generics
- 例如
let f<'a> () = nameof<'a>
- 注意到此处语法略有不同
- 例如
- Nameof in pattern matching
- 可以用在match中,例如
| nameof str -> "It's 'str'!"
- 可以用在match中,例如
- Nameof with instance members
- 可以通过现例来获取成员名字
- 如果没有现例,则需要通过Unchecked.defaultof
- 例如:
nameof Unchecked.defaultof<MyRecord>.MyField
- 例如:
- Syntax
- Caller information
- 文首
- 可以获取调用者信息,例如文件路径,行数,成员名等等
- 使用到下面的属性
- CallerFilePath
- CallerLineNumber
- CallerMemberName
- Example
- 也就是在被调用者处使用上述的属性指定额外的参数
- Remarks
- 这些属性迫使编译器写入额外的信息
- Member names
- 给出了编译器生成的成员名字的一些例子
- 文首
- Source Line, File, and Path Identifiers
- Syntax
__LINE__
__SOURCE_DIRECTORY__
__SOURCE_FILE__
- Remarks
- 这些标识符不是预处理器阔集,而是内建的值
- 计算这些值的时候,会考量
#line
指示
- 计算这些值的时候,会考量
- 这些标识符不是预处理器阔集,而是内建的值
- Syntax
- Plain text formatting
- 对于printf, printfn, sprintf的使用
- Attributes
- Type Providers
- Overview
- 文首
- 生成Provided Types,比如SQLProvider
- Generative and Erased Type Providers
- 两种形式:Generative以及Erased
- Generative可以生成.NET类型,写入装配件中,供其他装配件使用
- Erasd只在本地工程中使用,不写入装配件
- 两种形式:Generative以及Erased
- Commonly used Type Providers
- FSharp.Data
- SQLProvider
- (其余略)
- 文首
- Create a Type Provider
- 文首
- information rich programming(额)
- 又一些例子:
- SwaggerProvider
- FSharp.Data.SqlClient
- Before You Start
- 必须要有稳定的schema
- A Simple Type Provider
- (难道是typescript?)
- F# Type Provider SDK
- 文首
- Overview
https://fsharp.org
- Guide - Data Science with F#
- 文首
- F#在此处的优势是efficient execution, REPL-scripting, powerful libraries and scalable data integration.
- Jupyter Notebooks
- Integrated Packages
- http://fslab.org/项目孵化实验室
- https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet/微软赞助的开源项目
- https://scisharp.github.io/SciSharp/整合既有的项目,比如TensorFlow、Keras、PyTorch、Numpy等等。
- Interactive Charting
- XPlot,基于JS的图表工具
- Plotly.NET,基于Plotly
- Individual Packages
- 过
- Commercial packages
- 过
- Interoperability
- F# and Excel
- F# and R
- F# and MATLAB
- F# and Python
- F# and Mathematica/Wolfram Language
- 文首
- Guide - Data Access with F#
- CSV, HTML, JSON and XML data
- FSharp.Data,实现了对(CSV, HTML, JSON以及XML)甚至更复杂数据的访问
- Json.NET
- SQL Data Access
- FSharp.Data.SQLProvider
- (其余略)
- NoSQL Data Access
- (略)
- CSV, HTML, JSON and XML data
其他
- https://learn.microsoft.com/en-us/dotnet/fsharp/scenarios/web-development
- https://fsprojects.github.io/
- https://devblogs.microsoft.com/dotnet/category/fsharp/
- https://devblogs.microsoft.com/dotnet/announcing-fsharp-7/
- <fsharpforfunandprofit.com/>
一些例子:
- https://stackoverflow.com/questions/46697298/whats-the-best-way-to-parse-yaml-in-f-on-net-core
- https://stackoverflow.com/questions/30901269/f-and-yamldotnet
(底线)