F#奇妙游(1):F#浅尝

F#奇妙游(1):F#浅尝

是什么

F#是.NET平台的OCaml。

这句话很欠打,.NET和OCaml前者知道的人有一些,后者就很少了。.NET平台是一个开源的软件平台,早期由微软主导,目前已经开源,由.NET基金会维护。

OCaml是一种函数式编程语言,它的类型系统非常强大,支持多态、类型推断、类型参数化等特性。有很多编译器早期都是利用OCaml实现的,比如LLVM,Rust等。OCaml也是一个不纯的函数式语言,它支持面向对象编程、命令式编程等多种编程范式。

F#是OCaml的一个子集,它的语法和OCaml不能说非常相似,只能说完全相同。它的类型系统为适应.NET平台进行了大量改造,可以完全应用与.NET平台的各类开发活动。

为什么

为什么要学习F#,这个问题的答案有很多,我自己的理由非常简单:

  • 语言本身非常有趣(最重要的是fan-base几乎不存在,不会惹人讨厌)
  • .NET平台很有前途(并不是,划掉)

如果要按照语言警察和语言使徒开展传教活动的惯例,需要列一列语言的主要特征:

  • 强类型/静态类型,支持类型推断和类型参数化
  • 可编译,提供交互式环境
  • 模式匹配
  • 异步、并发
  • 并非纯函数式语言,多范式
    • 函数式编程
      • 响应式
      • 高阶函数,函数组合
    • 面向对象编程
    • 命令式编程
    • 泛型编程
    • 元编程

怎么做

安装

F#是.NET平台的一部分,所以安装.NET Core SDK就可以了。比如在Windows上,可以从这里下载安装包。安装7.0、8.0-preview什么的都行。

安装完成后,可以在命令行中输入dotnet --version来检查是否安装成功。然后能使用dotnet命令来创建F#项目,启动交互式环境等。运行dotnet --help就能看到所有的命令。MSDN提供了一个入门教程。这个教程有中文版,但是翻译的很烂,建议看英文版。

交互式环境

F#提供了一个交互式环境,可以在其中编写F#代码,然后立即执行。这个环境叫做F# Interactive,简称F# REPL。

dotnet fsi

来个Hello World,编辑一个文件,比如hello.fsx,然后在文件中输入:

printfn "Hello World"

然后在命令行中输入:

dotnet fsi hello.fsx

就能看到输出了。

奇妙游

普普通通的dotnet new console -lang F# -o HelloWorld就能创建一个F#的控制台项目。然后切换到Helloworld目录再运行dotnet run就OK。但是这么普普通通的项目没什么意思,我们来做点有意思的事情。

我们新建一个工程文件, winformfsharp.fsproj,内容如下:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <PublishSelfContained>false</PublishSelfContained>
    <PublishSingleFile>true</PublishSingleFile>
  </PropertyGroup>
  
  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

</Project>

然后新建一个文件,Program.fs,内容如下:

open System
open System.Windows.Forms
open System.Drawing

module MainForm =
    // 自定义操作符||>,用于简化代码
    let inline (||>) x f =
        f x
        x
    // 定义输入文字的控件
    let edit = new TextBox(Text = "World", Dock = DockStyle.Fill)
    let getGreeting msg = $"Hello, %s{edit.Text} %s{msg}!"
    
    // 定义按钮控件
    let button =
        new Button(Text = "Click Me!", Dock = DockStyle.Fill)

    // 定义输出文字的控件
    let textArea =
        new TextBox(Text = "Hello, World!", Multiline = true, Dock = DockStyle.Fill, ReadOnly = true)
        ||> fun t ->
            button.Click.Add(fun _ ->
                t.Text <- t.Text + Environment.NewLine + getGreeting "from F#"
                t.ScrollBars <- ScrollBars.Both
                t.Select (t.TextLength, 0)
                t.ScrollToCaret ()
                )
        // 自定义的操作符||>,设置事件函数,返回对象

    // 定义布局
    let layout =
        new TableLayoutPanel(Dock = DockStyle.Fill, ColumnCount = 2, RowCount = 2)
        ||> fun l ->
            l.Controls.Add(edit, 0, 0)
            l.Controls.Add(button, 1, 0)
            l.Controls.Add(textArea, 0, 1)
            
            l.SetColumnSpan(textArea, 2)
            l.PerformLayout()

    // 定义窗口
    let form =
        new Form(
            Text = "F# Form!",
            Width = 300,
            Height = 200,
            StartPosition = FormStartPosition.CenterScreen,
            Font = new Font("Consolas", 12.0f, FontStyle.Regular, GraphicsUnit.Point, byte 0uy),
            MaximizeBox = false,
            MinimizeBox = false,
            AcceptButton = button
        )
        ||> fun f -> f.Controls.Add(layout)

    // 定义入口
    [<EntryPoint>]
    [<STAThread>]
    let main argv =
        Application.EnableVisualStyles()
        Application.Run(form)
        0

然后在命令行中运行dotnet run,就能看到一个窗口了。

APP界面

总结

  1. F#是一门非常有趣的语言,可以用来做很多事情。
  2. F#的语法非常简洁别扭,但是有时候也会让人摸不着头脑。
  3. F#的类型系统非常强大,但是有时候也会让人摸不着头脑。
  4. F#的类型推断非常强大,但是有时候也会让人摸不着头脑。

我的头早就被摸秃了,所以我喜欢F#。

posted @ 2023-06-29 09:56  大福是小强  阅读(29)  评论(0编辑  收藏  举报  来源