Created
February 22, 2012 14:45
-
-
Save einblicker/1885393 to your computer and use it in GitHub Desktop.
F#でGADTsを実現する二つの方法
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module FPStyle = | |
[<AbstractClass>] | |
type Eq<'A, 'B> private () = | |
abstract F : 'A -> 'B | |
abstract G : 'B -> 'A | |
static member Id<'A>() = | |
{ new Eq<'A, 'A>() with | |
member this.F(x) = x | |
member this.G(x) = x } | |
[<AbstractClass>] | |
type Term<'T> internal () = class end | |
[<Sealed>] | |
type Zero<'T> private (ev : Eq<int, 'T>) = | |
inherit Term<'T>() | |
member this.Ev = ev | |
static member make() = Zero(Eq<int, 'T>.Id()) | |
[<Sealed>] | |
type Succ<'T> private (prev : Term<'T>, ev : Eq<int, 'T>) = | |
inherit Term<'T>() | |
member this.Ev = ev | |
member this.Prev = prev | |
static member make(t) = Succ(t, Eq<int,'T>.Id()) | |
let (|Zero|Succ|) (term : Term<'T>) = | |
match term with | |
| :? Zero<_> as term -> Zero(term.Ev) | |
| :? Succ<_> as term -> Succ(term.Prev, x.Ev) | |
| _ -> failwith "invalid case" | |
//F#でも多相再帰な関数は書ける。 | |
//ただし型推論は出来ない。多相再帰する場合には型を明記する必要がある。 | |
let rec eval term = | |
match term with | |
| Zero ev -> 0 |> ev.F | |
| Succ (t, ev) -> ev.G (eval t) + 1 |> ev.F | |
module OOPStyle = | |
[<AbstractClass>] | |
type public Term<'T> internal () = | |
abstract Eval : unit -> 'T | |
[<Sealed>] | |
type Zero() = | |
inherit Term<int>() | |
override this.Eval() = 0 | |
[<Sealed>] | |
type Succ(prev : Term<int>) = | |
inherit Term<int>() | |
member this.Prev = prev | |
override this.Eval() = prev.Eval() + 1 | |
//コードを一箇所に集めたいならVisitorパターンを使う | |
//Visitorパターンを使うときにtype equalityを表す項を一緒に渡さないと駄目 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://alaska-kamtchatka.blogspot.jp/2010/08/polymorphic-recursion-with-rank-2.html
新しいversionのOCamlだとpolymorphic recursionはmodule無くてもイケるとのこと。