F#で

シンプルな API 

を作ろう

About Me


twitter

GitHub

作ったもの
  • Doma : JavaのO/Rマッパー
  • Soma : F#で作った.NETのO/Rマッパー 
  • Tranq : F#専用DBアクセスライブラリ

題材


Web アプリケーションフレームワーク

Sinatraとか
Scalatraとか

Ruby : Sinatra

シンプル!


require 'sinatra' get '/hi' do
"Hello World!"end

Scala : Scalatra

シンプル!


import org.scalatra._ class ScalatraExample extends ScalatraServlet { get("/hi") { <h1>Hello World!</h1> } }

F# : Enku

し、シンプル??
open System
open System.Web.Http
open System.Web.Http.SelfHost
open Newtonsoft.Json.Serialization
open Enku
let config = new HttpSelfHostConfiguration("http://localhost:9090/")
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver 
  <- CamelCasePropertyNamesContractResolver()
let route = Routing.route config

route "hi" <| fun _ -> 
  [ 
    get, fun req -> async { 
      return Content.html "<h1>Hello World!</h1>" |> Response.Ok }
  ], fun req e -> Content.error e |> Response.InternalServerError

let server = new HttpSelfHostServer(config)
server.OpenAsync().Wait()

F# : Enku 

本質的な部分はシンプル!
(前頁のコードを微調整してます)

route "hi" <| fun _ -> [ get, fun _ -> async { return html "<h1>Hello World</h1>" |> Ok } ]

シンプルにするために

  • 短い名前
  • 丸括弧を避ける
  • 関数のタプル
  • 関数のタプルのリストを返す関数

 route "hi" <| fun _ ->
  [ 
    get, fun _ -> async { 
      return html "<h1>Hello World!</h1>" |> Ok } 

post <|> put, fun _ -> async { return html "<h1>Thank You!</h1>" |> Ok } ]

クラス?


let hiController req = let h1 text = html <| sprintf "<h1>%s</h1>" text [ get, fun _ -> async { return h1 "Hello World!" |> Ok } post, fun _ -> async { return h1 "Thank You!" |> Ok } ] route "hi" hiController
コンストラクタ、メンバ、属性

本当のクラスより良いところ

関数合成できる
たとえば、メソッド(に相当する関数)のインターセプタ
route "hi" <| fun _ ->
  [ 
    get, around [log] <| fun _ -> async { 
      return html "<h1>Hello World!</h1>" |> Ok } 
  ]
たとえば、属性(に相当する関数)の合成

route "hi" <| fun _ -> [ get <|> ajax, fun _ -> async { return html "<h1>Hello World!</h1>" |> Ok } ]

本当のクラスよりも悪いところ


  • シグネチャが複雑になりがち
    • typeで別名つけたり判別共用体で緩和できる
  • メソッド相当の関数のシグネチャはどれも同じ
  • メソッド相当の関数を明示的には呼び出せない
    • 名前がない
    • 名前をつけたとしてもタイプセーフには呼べない


まとめ


  • 関数、タプル、リストの組み合わせでシンプルに
  • クラスっぽい構造が作れる
    • 場合によっては本物のクラスよりよい選択かも?
    • リフレクションで処理される前提のクラスの代わりとか
      • 例) ASP.NET MVCのController

F# でシンプルなAPIを作ろう

By nakamura_to

F# でシンプルなAPIを作ろう

  • 2,113