Skip to content

Instantly share code, notes, and snippets.

@pocketberserker
Last active September 30, 2016 22:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pocketberserker/0953e71725a445f15caa to your computer and use it in GitHub Desktop.
Save pocketberserker/0953e71725a445f15caa to your computer and use it in GitHub Desktop.
歌舞伎座.tech#9「異種プログラミング言語格闘勉強会」 F# 枠

FSharpの紹介

歌舞伎座.tech#9「異種プログラミング言語格闘勉強会」の資料

CC BY-SA 4.0

前置き

  • 平和に生きたいので戦いませんどうせ負ける
  • 今回ほぼ唯一のML枠ですがMLっぽい話はしません
  • 時間がないので一部説明なしの単語が登場します。あらかじめご了承ください。

自己紹介

icon

  • なかやん・ゆーき / ぺんぎん / もみあげ
  • @pocketberserker / id:pocketberserker
  • Microsoft MVP for F# Visual Studio and Development Technologies (~ 2016/03/31)
    • カテゴリの変更が激しい…
  • F#は前職で使っていたようだ?
  • たぶんドワンゴ唯一のF#勢です

F# is 何

F#触ってみたい方へ

  • Visual Studio Community Edition入れましょう
    • F# のオプションにチェックいれないと入りません
  • mono 4.2.2ならF#も一緒についてくる…はず

日本のえふしゃーぷ事情

(日本のF#事情と世界のF#事情は異なるので、そのあたりを考慮してください)

見どころ紹介?

  • 細かいものから大きなものまで
  • (たぶん)発表者の好みが混ざってます

デフォルトイミュータブル

// イミュータブル
let a = 1
// ミュータブル
let mutable b = 2
  • mutableという長さが良い
    • 普段使わないやつに長いのキーワード
    • Scalaのvarはちょっと好きではない
    • finalとかconstは普段使いするには長すぎる(でも使う)

型パラメータ

ジェネリック(ジェネリクス?)とかそのあたり。

// 代数的データ型
type Tree<'T> =
  | Leaf of 'T
  | Node of Node<'T> * 'T * Node<'T>
  • 'Tが型パラメータ。'が必要。
  • 地味だが、通常の型と区別がつきやすいので便利

変性(variance)

"F# generic types do not support covariance or contravariance." ("The F# 4.0 Language Specification" 4.5.2 の Noteより抜粋)

制約

C# よりも数が多い

シャドーイング

// 引数のxはint option
let hoge x =
  // このxはint
  let x =
    match x with
    | Some x ->
      // ここはint
      x
    | None -> 0
  x + 1
  • 同じ名前を付けたいときがあるのです

型推論

  • わりと効く
    • もちろんやりすぎは危険なので、publicなAPIには型を書くべき
    • たまに気を利かせたつもりでobjに推論したりするので慢心ダメゼッタイ
  • |>やモジュールを組み合わせることで推論できるパターンもあったりする

人によって評価が異なるので省略

  • オフサイドルール
  • letlet rec
  • 基本は前方参照
    • 前方で定義したものしか使えない

Units of Measure

一部の数値型に単位をつけられる

[<Measure>] type g
[<Measure>] type kg

let g2kg (x : float<g>): float<kg> = x / 1000.0<g/kg>
  • 単位はコンパイル時にerase
    • パフォーマンスには影響しない

コンピュテーション式

順番に配列したり結合可能な計算を記述するのに便利な構文を提供するための機能。 機能制限版マクロ…?

"The F# 4.0 Language Specification" の 6.3.10 に書かれた変換規則でもって変換を行う。

一番わかりやすい使われ方はモナド用構文(do記法やfor式みたいなやつ)。 あるいはasync awaitのようなやつ。

type OptionBuilder() =
  member __.Bind(x, f) = Option.bind f x
  member __.Return(x) = Some x
  
let option = OptionBuilder()

// これはNoneが返る
option {
  let x = Some 1
  let y = None
  return x + y
}

とはいえ、ただ変換規則に沿ってメソッド呼び出しに展開しているだけなので別の挙動にもできる。

// https://github.com/BasisLib/Basis.Core/blob/f48ed463699ae0235aa58623d0f46c754a6f7326/Basis.Core/ComputationExpr.fs#L9
// 上記のビルダーを使えばC#っぽい挙動にもできる
option {
  let x = Some 2
  if x % 2 = 0 then return x * 2
  return -1
}
// このコンピュテーション式はSome 4を返す

TypeProvier

"コンパイル時にコード生成に頼らずに型を生成する仕組み"です。 なんのこっちゃ。

不満点は

色々ありすぎて困るが、大きな点で述べると

  • higher kinded polymorphismがない
  • varianceの関係でF#単独でHListを実装できない(たぶん)
  • 網羅した形の日本語の資料, 書籍が少ない
    • つらい
  • type eraseではないCLIの仕様に寄り添う方針なのでつらいときがある

正直、資料や書籍の件以外は業務で使う分には問題にならないです、ええ。

余談:如何にして私は心配するのをやめてこの言語を愛するようになったか

愛憎入り混じっているので語れない。

文法(時間ないだろうけどあれば)

OCaml + .NETが合体するとこうなるのか…と思いながら見てください。

let a = 1

let fizzbuzz n =
  match (n % 3, n % 5) with
  | 0, 0 -> "FizzBuzz"
  | 0, _ -> "Fizz"
  | _, 0 -> "Buzz"
  | _ -> string n
  
let hoge x =
  let rec inner acc x =
    if x > 0 then
      inner (acc + x) x - 1
    else acc
  inner 0 x

type Person = {
  FirstName: string
  LastName: string
}

let zd = {
  FirstName = "ずん"
  LastName = "どこ"
}

type IHoge =
  abstract Foo: int -> string

[<AbstractClass>]
type AbstractHoge() =
  abstract member Foo: int -> string

type Fuga() =
  inherit AbstractHoge()
  override __.Foo(x) = string x
  interface IHoge with
    member this.Foo(x) = this.Foo(x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment