F#是.NET平台上的函算式语言。

  • What is F#
  • Get Started
    • Get Started
      • Get started online
        • 有Fable REPL和JupyterNotebook版本可用。
  • F# Language Guide
  • F# language reference
  • 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
      • 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 recmatch
        • 完整支持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, 似乎是为函算式编程特别准备的一章。

  • F# tools
    • F# Development 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# 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
        • 可以重载类型的方法,但是补能重载一个算函
    • 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
    • Inline Functions
      • (未读)
    • Function Expressions
      • (未读)
  • Loops and conditionals
  • Pattern matching
    • Overview
      • Remarks
        • 语法
          match expression with
          | pattern [ when condition ] -> result-expression
          ...
          
        • pattern的种类可以好多
    • 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(略)
  • Types and inference
  • Records and unions
    • Discriminated Unions
      • 文首
        • 简单说DU可以将多个不同类型合为一个,也就是给heterogeneous数据的处理提供支持
        • 要知道,F#中的List,以及其他大多数类型,其实是homegeneous的
      • Syntax(过)
      • Remarks
        • 可以光指定case名字,这样一来,表现得像个枚举
        • case的域属可以匿名
        • 可以用case构造此类型,构造的时候域属顺序可以打乱
        • 比如option类型是这么定义的
          type Option<'a> =
              | Some of 'a
              | None
          
          option是Option的别名
        • 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
      • Struct Discriminated Unions
        • 可以将DU表示为struct,只要加上|<Struct>|属性,这样就变成了量值类型了
        • 但是存在一些考量
          • 会被像量值一样拷贝
          • 无法定义使用递归类型
          • 多case情况下,必须提供独特的case名字
      • Using Discriminated Unions Instead of Object Hierarchies
        • 可以作为简单的客件层次的替代
        • 使用码取,而不是虚算函机制来按具体case操作
      • Using Discriminated Unions for Tree Data Structures
        • 介绍了二叉树的例子
        • 还有一个编程语言表达式的例子
      • Members
        • 可以定义member,以及可以实现接口
      • Common attributes
        • 有下面几种属性可以使用
          • [<RequireQualifiedAccess>]
          • [<NoEquality>]
          • [<NoComparison>]
          • [<Struct>]
  • 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
      • 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绑定只在标类中使用,并不是真正的成员
    • 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关键字
  • 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
    • Value Options
      • 在满足以下情况的时候使用
        • 适合使用Option
        • 同时适合使用struct
  • 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
  • Reflection
    • Attributes
      • Syntax
        • 形如:[<target:attribute-name(arguments)>]
      • Remarks
        • target是可选的
        • 一个例子
          [<DllImport("kernel32", SetLastError=true)>]
          extern bool CloseHandle(nativeint handle)
          
        • 属性不可以用于let绑定之上
        • 对于属性目标assemblymodule,可应用于顶层的do绑定之上
        • 需要属性标类具有System.AttributeUsageAttribute类型的属性
        • 表格中列出了属性目标:assembly, module, return, field, property, param, type
    • 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'!"
      • Nameof with instance members
        • 可以通过现例来获取成员名字
        • 如果没有现例,则需要通过Unchecked.defaultof
          • 例如:nameof Unchecked.defaultof<MyRecord>.MyField
    • Caller information
      • 文首
        • 可以获取调用者信息,例如文件路径,行数,成员名等等
        • 使用到下面的属性
          • CallerFilePath
          • CallerLineNumber
          • CallerMemberName
        • Example
          • 也就是在被调用者处使用上述的属性指定额外的参数
        • Remarks
          • 这些属性迫使编译器写入额外的信息
        • Member names
          • 给出了编译器生成的成员名字的一些例子
    • Source Line, File, and Path Identifiers
      • Syntax
        • __LINE__
        • __SOURCE_DIRECTORY__
        • __SOURCE_FILE__
      • Remarks
        • 这些标识符不是预处理器阔集,而是内建的值
          • 计算这些值的时候,会考量#line指示
    • Plain text formatting
      • 对于printf, printfn, sprintf的使用
  • Type Providers
    • Overview
      • 文首
        • 生成Provided Types,比如SQLProvider
      • Generative and Erased Type Providers
        • 两种形式:Generative以及Erased
          • Generative可以生成.NET类型,写入装配件中,供其他装配件使用
          • Erasd只在本地工程中使用,不写入装配件
      • 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

https://fsharp.org

其他

一些例子:

(底线)