About F#
(*F#数据类型*) let sbyte=42y //y <=> Y let byte=45uy //uy let int16=42s //s <=> S let uint16=42us //us let int=12 // //<=> int32 let uint32=42u //U let int64=54L //L let uint64=45UL //UL let bigint=78I //I //至少4个字节 任何整数 let float32=42.0F //F //32位有符号浮点数(7个有效位) //4个字节 //±1.5E-45至±3.4E38 let float=42.0 // //64位有符号浮点数(15-16有效位) //8个字节 //±5.0E-324到±1.7e308 let decimal=42.0M //M //128位有符号浮点数(28-29有效位) //16字节 //±1.0E-28±7.9e28 let BigRational=42N //N //任意精度有理数。 使用此类型需要引用FSharp.PowerPack.dll。 //至少4个字节 //任意有理数。 let char='x' //单个Unicode字符 //U + 0000至U + FFFF //2个字节 let string="fdg" //Unicode文本 //0至约2十亿个字符 //20 +(2 *字符串的长度)个字节 let bool=true (*F#变量*) let x=10 //声明 //F#中的变量是不可变的 let mutable x = 10 //可变变量 x <- 15 //赋值 (*F#运算符*) // + // - // * // / // % // ** 指数运算符 // == // <> // > // < // >= // <= // && // || // not // &&& 按位与 // ||| 按位或 // ^^^ 逐位异或 // ~~~ 按位取反 // <<< 左移 // >>> 右移 (*F#决策*) if expr then expr if expr then expr else expr if expr then expr elif expr then expr else expr (*F#循环*) for var = start-expr to end-expr do loop for var = start-expr downto end-expr do loop for pattern in enumerable-expression do body-expression [ 10; 25; 34; 45; 78 ] //list seq { for i in 1 .. 10 -> (i, i*i) } //seq while test-expression do body-expression (*F#功能*) let [inline] function-name parameter-list [ : return-type ] = function-body let doubleIt (x : int) : int = 2 * x //定义一个函数 let vol = cylinderVolume 3.0 5.0 //调用函数 函数名 参数 let rec function-name parameter-list = recursive-function-body let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2) //递归函数 //输入数据类型 -> 输出数据类型 fun x y -> x * y (*<=>*)let mul x y = x * y //Lambda表达式 (fun x y -> x * y) 5 7 //引用 let function1 x = x + 1 let function2 x = x * 5 let f = function1 >> function2 f 10 //函数组合 let function1 x = x + 1 let function2 x = x * 5 let res = 10 |> function1 |> function2 //流水线 (*F#字符串*) // \n \r \t \\ \" \' \u6A54 \U78A87B2 // @"" // """ """ String.collect (fun c -> sprintf "%c " c) "this is string" //collect : (char → string) → string → string //构建一个新的字符串,其字符是应用特定的功能到每个输入字符串的字符的并且链接该产生的串的结果。 String.concat "连接字符串" [ "Tutorials Point"; "Absolute Classes" ] //concat : string → seq<string> → string //将一个字符串分隔一个给定的序列,并返回一个新字符串。 String.replicate 10 "*! " //replicate : int → string → string //通过串联串的实例中指定数量返回一个字符串 //exists : (char → bool) → string → bool //如果字符串的任何字符满足给定谓词测试。 //forall : (char → bool) → string → bool //如果测试字符串中的所有字符满足给定谓词 //init : int → (int → string) → string //创建一个新的字符串,其字符是应用特定的功能到每个索引和连接生成的字符串的结果。 //iter : (char → unit) → string → unit //通过使用指定的函数在字符串中的每个字符。 //iteri : (int → char → unit) → string → unit //通过使用指定的功能的字符串中的每个字符和字符本身的索引。 //length : string → int //返回字符串的长度。 //map : (char → char) → string → string //创建一个新的字符串,其字符是应用特定的功能到每个输入字符串的字符的结果。 //mapi : (int → char → char) → string → string //创建一个新的字符串,其字符是施加指定的函数来输入字符串的每个字符和索引的结果。 (*F#选项*) let div x y = match y with | 0 -> None | _ -> Some(x/y) None //'T option //静态属性,使您能够创建具有None值的选项值。 IsNone //bool //如果该选项的none值,则返回true。 IsSome //bool //如果该选项的值是不无返回true。 Some //'T option //一个静态成员,它创建一个值为notNone的选项。 Value //'T //返回基础值,如果值为None,则抛出NullReferenceException。 (*F#元组*) ( "Absolute Classes", 1, 2.0 ) //元组是一个逗号分隔的值集合。 这些用于创建特殊数据结构,将相关值组合在一起 fst(23, 30) //返回2元组中的第一项 snd(23, 30) //返回2元组中的第二项 (*F#记录*) type website = { title : string; url : string } //记录类似于一个元组,但它包含命名字段 let homepage = { Title = "TutorialsPoint"; Url = "www.w3cschool.cn" } //创建记录 (*F#列表*) let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] //列表是相同类型的有序,不可变系列元素。 它在某种程度上等同于链表数据结构。 let list5 = List.init 5 (fun index -> (index, index * index)) //使用List模块的List.init方法 //[(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)] let list3 = [1 .. 10] //列表解析 //范围有构造 // [start .. end] let list6 = [ for a in 1 .. 10 do yield (a * a) ] //生成器有构造 //[for x in collection do ... yield expr] list1.IsEmpty //第一个元素 Empty //静态属性,返回相应类型的空列表 IsEmpty //如果列表中没有的元素,返回true Item //(从零开始)指定索引处的元素 Length //元素的数量 Tail //没有第一元件列表 (*F#序列*) seq { expr } //序列,像列表一样表示值的有序集合。 然而,当需要时,计算序列或序列表达式中的元素。 它们不是一次计算的,因此它们用于表示无限数据结构。 seq { for a in 1 .. 10 do yield a*a } //seq [1; 4; 9; 16; ...] seq { 1 .. 5 .. 50 } //seq [1; 6; 11; 16; ...] (*F#集合*) Set.empty.Add(3).Add(5).Add(7). Add(9) //集合是一种数据结构,用作项目的集合,而不保留插入项目的顺序。 集合不允许将重复条目插入到集合中。 Set.ofList ["mon"; "tues"; "wed"; "thurs"; "fri"] Set.ofSeq [ 1 .. 2.. 10 ] (*F#地图*) Map.empty.Add("Zara Ali", "1501").Add("Rishita Gupta", "1502") //Map是一种特殊类型的集合,将值与键相关联。 以与创建集合类似的方式创建Map。 Add //返回与绑定添加到给定的地图新地图。 ContainsKey //测试元素是否在地图中的域。 Count //在地图上绑定的数量。 IsEmpty //如果在地图上没有绑定,则返回true。 Item //查找地图中的元素。如果没有绑定存在于地图引发KeyNotFoundException。 Remove //从地图中删除域的元素。如果该元素不存在任何异常。 TryFind //在地图中查找元素,如果元素在地图的域中,则返回一个值,而不是None (*F#差别联合*) type VoltageState = | High of string | Low of double * double type type-name = | case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] type2 ...] | case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...] ... //联合(Unions)或差别联合(discriminated unions)允许您构建表示明确定义的一组选择的复杂数据结构 (*F#数组*) [| 1; 2; 3; 4; 5; 6 |] //数组是固定大小的,基于零的,可变的所有相同类型的连续数据元素的集合。 array.[0] //访问数组元素 (*F#可变列表*) let booksList = new List<string>() //List <T>类表示可以通过索引访问的对象的强类型列表。 booksList.Add("Gone with the Wind") // booksList.Capacity //获取或设置内部数据结构可以保持不调整元件的总数量。 booksList.Count //获取包含在列表(T)的元素的数量 booksList.Item //获取或设置元素指定索引处。 (*F#可变字典*) let dict = new Dictionary<string, string>() //Dictionary<'TKey, 'TValue>类是F#映射数据结构的可变模拟,并且包含许多相同的功能。 (*F#基本I / O*) bprintf : StringBuilder → BuilderFormat<'T> → 'T //打印到一个StringBuilder。 eprintf : TextWriterFormat<'T> → 'T //打印格式化输出到stderr。 eprintfn : TextWriterFormat<'T> → 'T //打印格式化输出到stderr,增加一个换行符。 failwithf : StringFormat<'T,'Result> → 'T //打印到一个字符串缓冲区,提高与给定结果的异常。 fprintf : TextWriter → TextWriterFormat<'T> → 'T //打印到一个文本作家。 fprintfn : TextWriter → TextWriterFormat<'T> → 'T //打印到文本编写,添加一个换行符。 sprintf : StringFormat<'T> → 'T //打印到一个字符串使用内部字符串缓冲区并返回结果为一个字符串。 printfn : TextWriterFormat<'T> → 'T //打印格式化输出到标准输出,增加一个换行符。 printf : TextWriterFormat<'T> → 'T //打印格式化输出到标准输出。 kbprintf : (unit → 'Result) → StringBuilder → BuilderFormat<'T,'Result> → 'T //就像bprintf一样,但是调用指定的函数来生成结果。 kfprintf : (unit → 'Result) → TextWriter → TextWriterFormat<'T,'Result> → 'T //就像fprintf,但是调用指定的函数来生成结果。 kprintf : (string → 'Result) → StringFormat<'T,'Result> → 'T //如printf,而是调用指定的函数生成的结果。例如,这些让印刷力的冲洗后的所有输出已输入到信道,而不是之前。 ksprintf : (string → 'Result) → StringFormat<'T,'Result> → 'T //像sprintf一样,但调用指定的函数来生成结果。 格式占位符的语法是 %[flags][width][.precision][type] %b //格式化为bool,格式为true或false。 %C //格式化字符。 %S //格式化一个字符串,格式为其内容,而不解释任何转义字符。 %D,%I //格式格式化为十进制整数任何基本的整数类型,如果基本的整数类型的签署。 %U //格式化格式化为一个无符号十进制整数任何基本的整数类型。 %X //格式格式化为无符号十六进制整数任何基本的整数类型,使用A到F小写字母。 %X //格式格式化为无符号十六进制整数任何基本的整数类型,从A到F使用大写字母 %ο //格式化格式化为一个无符号的八进制整数任何基本的整数类型。 %E,%E,%F,%F,%G,%G //格式化使用C风格浮点格式规范格式化的任何基本浮点类型(float,float32)。 %E,%E //格式具有形式的符号值[ - ] d.dddde [星座] DDD其中d是一个十进制数,dddd为一个或多个十进制数字,ddd肯定三个十进制数字,符号为+或 - 。 %F //有格式化的形式符号值[ - ] dddd.dddd,其中dddd是一个或多个十进制数字。的小数点之前数量取决于数的大小,和数字的小数点后的数量取决于所要求的精度。 %G,%G //格式化f中或电子格式打印的符号值,取其对给定值和精度更紧凑。 %M //格式化一个十进制值。 %O //格式的任何值,拳击对象,并使用其ToString方法打印。 %A,%+ A //格式的任何值,印有默认的布局设置。使用%+ A打印识别联合的结构与内部和私人交涉。 % //一般格式说明,需要两个参数。第一个参数是一个接受两个参数的函数:第一,适当类型的给定格式化函数的上下文参数(例如,一个TextWriter的),二值打印和输出两种或返回相应的文本。第二个参数是打印的特殊价值。 %T //一般格式说明符需要一个参数:一个函数,它接受给定格式化函数(aTextWriter)的适当类型的上下文参数,并输出或返回适当的文本。 基本整数类型有byte,sbyte,int16,uint16,int32,uint32,int64,uint64,nativeint和unativeint。 基本浮点类型是float和float32。 0 //指定要添加零而不是空格来弥补所需的宽度。 - //指定要左对齐指定宽度内的结果。 + //指定要添加+字符如果数字为正(匹配 - 符号为负号)。 ' ' //(space) 指定要添加一个额外的空间,如果该数字为正数(匹配 - 号为负数)。 # //无效。 (*F#泛型*) let function-name<type-parameters> parameter-list = function-body // Explicitly generic function. [ static ] member object-identifer.method-name<type-parameters> parameter-list [ return-type ] = method-body // Explicitly generic method. type type-name<type-parameters> type-definition // Explicitly generic class, record, interface, structure,or discriminated union. (*F#委托*) type Delegate1 = delegate of (int * int) -> int //type delegate-typename = delegate of type1 -> type2 (*F#枚举*) type Days = | Sun = 0 | Mon = 1 | Tues = 2 | Wed = 3 | Thurs = 4 | Fri = 5 | Sat = 6 (*F#模式匹配*) let compareInt x = match x with | (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2 | (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2 | (var1, var2) -> printfn "%d equals %d" var1 var2 let greeting (name, subject) = match (name, subject) with | ("Zara", _) -> "Hello, Zara" | (name, "English") -> "Hello, " + name + " from the department of English" | (name, _) when subject.StartsWith("Comp") -> "Hello, " + name + " from the department of Computer Sc." | (_, "Accounts and Finance") -> "Welcome to the department of Accounts and Finance!" | _ -> "You are not registered into the system" let evaluatePoint (point: Point) = match point with | { x = 0.0; y = 0.0 } -> printfn "Point is at the origin." | { x = xVal; y = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal | { x = 0.0; y = yVal } -> printfn "Point is on the y-axis. Value is %f." yVal | { x = xVal; y = yVal } -> printfn "Point is at (%f, %f)." xVal yVal (*F#异常处理*) raise expr //引发给出例外。 failwith expr //引发System.Exception的异常。 try expr with rules //抓住表达式匹配模式规则。 try expr finally expr //当计算成功时以及当引发异常时,执行finally表达式。 | :? ArgumentException //规则匹配给定的.NET异常类型。 | :? ArgumentException as e //规则匹配给定的.NET异常类型,绑定名称e将异常对象值。 | Failure(msg) → expr //规则匹配给定的数据承载F#异常。 | exn → expr //规则匹配任何异常,结合EXN异常对象值的名称。 | exn when expr → expr //规则匹配给定条件下的例外,结合EXN异常对象值的名称。 let divisionprog x y = try Some (x / y) with | :? System.DivideByZeroException -> printfn "Division by zero!"; None let func1 x y = try try if x = y then raise (InnerError("inner error")) else raise (OuterError("outer error")) with | InnerError(str) -> printfn "Error:%s" str finally printfn "From the finally block." (*F#类*) // Class definition: type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] = [ class ] [ inherit base-type-name(base-constructor-args) ] [ let-bindings ] [ do-bindings ] member-list ... [ end ] // Mutually recursive class definitions: type [access-modifier] type-name1 ... and [access-modifier] type-name2 ... //1、type-name是任何有效的标识符。此公共的默认访问修饰符。 //2、type-params描述了可选的通用类型参数。 //3、parameter-list描述构造函数参数。主构造函数的默认访问修饰符是public。 //4、identifier用于给可选的as关键词指定名称或自我标识符,可以在类型定义中使用该名称来引用类型的实例。 //5、inherit关键字允许您为类指定基类。 //6、let绑定允许您声明该类的本地字段或函数值。 //7、do-bindings部分包括在对象构造时执行的代码。 //8、member-list表由其他构造函数,实例和静态方法声明,接口声明,抽象绑定以及属性和事件声明组成。 //9、标记定义的开始和结束的关键字class和end是可选的。 type Line = class val X1 : float val Y1 : float val X2 : float val Y2 : float new (x1, y1, x2, y2) as this = { X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;} then printfn " Creating Line: {(%g, %g), (%g, %g)}Length: %g" this.X1 this.Y1 this.X2 this.Y2 this.Length member x.Length = let sqr x = x * x sqrt(sqr(x.X1 - x.X2) + sqr(x.Y1 - x.Y2) ) end let aLine = new Line(1.0, 1.0, 4.0, 5.0) type Greetings(name) as gr = let data = name do gr.PrintMessage() member this.PrintMessage() = printf "Hello %s " data let gtr = new Greetings("Zara") (*F#结构*) [ attributes ] type [accessibility-modifier] type-name = struct type-definition-elements end // or [ attributes ] [<StructAttribute>] type [accessibility-modifier] type-name = type-definition-elements type Line = struct val X1 : float val Y1 : float val X2 : float val Y2 : float new (x1, y1, x2, y2) = {X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;} end let aLine = new Line(1.0, 1.0, 4.0, 5.0) (*F#运算符重载*) //overloading + operator static member (+) (a : Complex, b: Complex) = Complex(a.x + b.x, a.y + b.y) //implementing a complex class with +, and - operators //overloaded type Complex(x: float, y : float) = member this.x = x member this.y = y //overloading + operator static member (+) (a : Complex, b: Complex) = Complex(a.x + b.x, a.y + b.y) //overloading - operator static member (-) (a : Complex, b: Complex) = Complex(a.x - b.x, a.y - b.y) // overriding the ToString method override this.ToString() = this.x.ToString() + " " + this.y.ToString() let c1 = Complex(7.0, 5.0) let c2 = Complex(4.2, 3.1) let c3 = c1 + c2 (*F#继承*) type MyDerived(...) = inherit MyBase(...) type Person(name) = member x.Name = name abstract Greet : unit -> unit default x.Greet() = printfn "Hi, I'm %s" x.Name //重载方法,必须使用abstract和default关键字将方法声明为可覆盖 type Student(name, studentID : int) = inherit Person(name) let mutable _GPA = 0.0 member x.StudentID = studentID member x.GPA with get() = _GPA and set value = _GPA <- value override x.Greet() = printfn "Student %s" x.Name //重载方法 [<AbstractClass>] type Person(name) = member x.Name = name abstract Greet : unit -> unit //抽象类 (*F#接口*) [ attributes ] type interface-name = [ interface ] [ inherit base-interface-name ...] abstract member1 : [ argument-types1 -> ] return-type1 abstract member2 : [ argument-types2 -> ] return-type2 ... [ end ] interface interface-name with member self-identifier.member1 argument-list = method-body1 member self-identifier.member2 argument-list = method-body2 [ attributes ] let class-name (argument-list) = { new interface-name with member self-identifier.member1 argument-list = method-body1 member self-identifier.member2 argument-list = method-body2 [ base-interface-definitions ] } member-list //1、在接口声明中,成员未实现。 //2、成员是抽象的,由default关键字声明。 但是,您可以使用default关键字提供默认实现。 //3、您可以通过使用对象表达式或使用类类型实现接口。 //4、在类或对象实现中,您需要为接口的抽象方法提供方法体。 //5、关键字interface和end(标记定义的开始和结束)是可选的。 type Student(name : string, id : int) = member this.ID = id interface IPerson with member this.Name = name member this.Enter() = printfn "Student entering premises!" member this.Leave() = printfn "Student leaving premises!" type StuffMember(name : string, id : int, salary : float) = let mutable _salary = salary member this.Salary with get() = _salary and set(value) = _salary <- value interface IPerson with member this.Name = name member this.Enter() = printfn "Stuff member entering premises!" member this.Leave() = printfn "Stuff member leaving premises!" let s = new Student("Zara", 1234) let st = new StuffMember("Rohit", 34, 50000.0) (s :> IPerson).Enter() (s :> IPerson).Leave() (st :> IPerson).Enter() (st :> IPerson).Leave() type Interface1 = abstract member doubleIt: int -> int type Interface2 = abstract member tripleIt: int -> int type Interface3 = inherit Interface1 inherit Interface2 abstract member printIt: int -> string //接口继承 (*F#事件*) type Worker(name : string, shift : string) = let mutable _name = name; let mutable _shift = shift; let nameChanged = new Event<unit>() (* creates event *) let shiftChanged = new Event<unit>() (* creates event *) member this.NameChanged = nameChanged.Publish (* exposed event handler *) member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *) member this.Name with get() = _name and set(value) = _name <- value nameChanged.Trigger() (* invokes event handler *) member this.Shift with get() = _shift and set(value) = _shift <- value shiftChanged.Trigger() (* invokes event handler *) let wk = new Worker("Wilson", "Evening") wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name) wk.Name <- "William" wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!") wk.Name <- "Bill" wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift) wk.Shift <- "Morning" wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!") wk.Shift <- "Night" Publish //发布观察值作为第一类值。 Trigger //触发器使用给定参数的观察。 add : ('T → unit) → Event<'Del,'T> → unit //每个触发特定事件时运行给定的功能。 choose : ('T → 'U option) → IEvent<'Del,'T> → IEvent<'U> //返回时触发从原始事件选择消息的新事件。选择功能需要一个原始消息到可选的新消息。 filter : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> //返回监听到原始事件,只有当参数的事件传递给定的函数触发所得事件的新事件。 map : ('T → 'U) → IEvent<'Del, 'T> → IEvent<'U> //返回传递给定函数转换值的新事件。 merge : IEvent<'Del1,'T> → IEvent<'Del2,'T> → IEvent<'T> //触发输出事件时,无论是输入事件火。 pairwise : IEvent<'Del,'T> → IEvent<'T * 'T> //返回触发输入事件第二次和后续触发的新事件。 输入事件的第N次触发将来自第N-1和第N次触发的自变量作为一对传递。 传递到第N-1次触发的参数保持在隐藏内部状态,直到发生第N次触发。 partition : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> * IEvent<'T> //返回监听到原始事件并触发所述第一结果的事件,如果谓词事件参数的应用程序返回真一个新的事件,和第二事件,如果它返回false。 scan : ('U → 'T → 'U) → 'U → IEvent<'Del,'T> → IEvent<'U> //返回由施加给定的累积功能来触发输入事件的连续值的结果的一个新的事件。内部状态的一个项目记录状态参数的当前值。内部状态的累积功能的执行期间不被锁定,所以应注意,输入IEvent不是由多个线程同时触发。 split : ('T → Choice<'U1,'U2>) → IEvent<'Del,'T> → IEvent<'U1> * IEvent<'U2> //返回监听到原始事件并触发第一所得事件如果该函数的事件参数的应用程序返回一个Choice1Of2一个新的事件,并且如果它返回一个Choice2Of2第二事件。 VAL地址:事件:('T→单位)→单元 //连接侦听器函数事件。当事件被触发的监听器会被调用。 VAL的AddHandler:“德尔→单元 //连接处理程序委托对象的事件。处理程序可使用RemoveHandler在稍后删除。当事件被触发的监听器会被调用。 VAL RemoveHandler:“德尔→单元 // 移除事件侦听器店监听器委派。 (*F#模块*) // Top-level module declaration. module [accessibility-modifier] [qualified-namespace.]module-name declarations // Local module declaration. module [accessibility-modifier] module-name = declarations //根据MSDN库,F#模块是F#代码结构的分组,例如类型,值,函数值和do绑定中的代码。 它被实现为只有静态成员的公共语言运行时(CLR)类。 //根据整个文件是否包含在模块中的情况,有两种类型的模块声明: //1、顶层模块声明 //2、本地模块声明 //在顶层模块声明中,整个文件包含在模块中。 在这种情况下,文件中的第一个声明是模块声明。 您不必在顶层模块中缩进声明。 //在本地模块声明中,只有在该模块声明下缩进的声明是模块的一部分。 module Arithmetic let add x y = x + y let sub x y = x - y let mult x y = x * y let div x y = x / y open Arithmetic let addRes = Arithmetic.add 25 9 let subRes = Arithmetic.sub 25 9 let multRes = Arithmetic.mult 25 9 let divRes = Arithmetic.div 25 9 // Module1 module module1 = // Indent all program elements within modules that are declared with an equal sign. let value1 = 100 let module1Function x = x + value1 // Module2 module module2 = let value2 = 200 // Use a qualified name to access the function. // from module1. let module2Function x = x + (module1.module1Function value2) let result = module1.module1Function 25 printfn "%d" result let result2 = module2.module2Function 25 printfn "%d" result2 (*F#命名空间*) namespace [parent-namespaces.]identifier