Hinze(Haskell)の論文に記載されているように2-3本の指の木で遊んでみたかったです(blogも参照)。フィンガーツリーを実装するときのタイプエラー
type Node<'a> =
| Node2 of 'a * 'a
| Node3 of 'a * 'a * 'a
static member OfList = function
| [a; b] -> Node2(a, b)
| [a; b; c] -> Node3(a, b, c)
| _ -> failwith "Only lists of length 2 or 3 accepted!"
member me.ToList() =
match me with
| Node2(a, b) -> [a; b]
| Node3(a, b, c) -> [a; b; c]
type Digit<'a> =
| One of 'a
| Two of 'a * 'a
| Three of 'a * 'a * 'a
| Four of 'a * 'a * 'a * 'a
static member OfList = function
| [a] -> One(a)
| [a; b] -> Two(a, b)
| [a; b; c] -> Three(a, b, c)
| [a; b; c; d] -> Four(a, b, c, d)
| _ -> failwith "Only lists of length 1 to 4 accepted!"
member me.ToList() =
match me with
| One a -> [a]
| Two(a, b) -> [a; b]
| Three(a, b, c) -> [a; b; c]
| Four(a, b, c, d) -> [a; b; c; d]
member me.Append x =
match me with
| One a -> Two(a, x)
| Two(a, b) -> Three(a, b, x)
| Three(a, b, c) -> Four(a, b, c, x)
| _ -> failwith "Cannot prepend to Digit.Four!"
member me.Prepend x =
match me with
| One a -> Two(x, a)
| Two(a, b) -> Three(x, a, b)
| Three(a, b, c) -> Four(x, a, b, c)
| _ -> failwith "Cannot prepend to Digit.Four!"
[<NoComparison>]
[<NoEquality>]
type FingerTree<'a> =
| Empty
| Single of 'a
| Deep of Digit<'a> * FingerTree<Node<'a>> * Digit<'a>
type Digit<'a> with
member me.Promote() =
match me with
| One a -> Single a
| Two(a, b) -> Deep(One a, Empty, One b)
| Three(a, b, c) -> Deep(One a, Empty, Two(b, c))
| Four(a, b, c, d) -> Deep(Two(a, b), Empty, Two(c, d))
type View<'a> = Nil | View of 'a * FingerTree<'a>
私はちょうどviewl
機能の作業を取得することができない今、それは型の不一致文句:2-3フィンガーツリー<を期待
「>が、> 2-3フィンガーツリーを与えられました。
'' a 'と' Node < 'a>' FingerTree 'を統一すると、結果の型は無限になります。
let rec viewl : FingerTree<'a> -> View<'a> = function
| Empty -> Nil
| Single x -> View(x, Empty)
| Deep(One x, deeper(*:FingerTree<'a>/FingerTree<Node<'a>>*), suffix) ->
let rest =
match viewl deeper with
| Nil ->
suffix.Promote()
| View (node(*:Node<'a>*), rest) ->
let prefix = node.ToList() |> Digit<_>.OfList
Deep(prefix, rest, suffix)
View(x, rest)
| Deep(prefix, deeper, suffix) ->
match prefix.ToList() with
| x::xs ->
View(x, Deep(Digit<_>.OfList xs, deeper, suffix))
| _ -> failwith "Impossible!"
私はprepend
で前にこのエラーが発生しましたが、機能上の完全な型情報を追加することによって、それを解決することができました。 viewl
については
// These three/four type annotations solved the problem.
let rec prepend<'a> (a:'a) : FingerTree<'a> -> FingerTree<'a> = function
| Empty -> Single a
| Single b -> Deep(One a, Empty, One b)
| Deep(Four(b, c, d, e), deeper, suffix) ->
Deep(Two(a, b), prepend (Node3(c, d, e)) deeper, suffix)
| Deep(prefix, deeper, suffix) ->
Deep(prefix.Prepend a, deeper, suffix)
これは十分ではないようですので、私はまた、(コメントを探してください)関数の途中でタイプを追加しようとしました。それはうまくいかなかった。
私はある種のエラーを理解しており、どこから来ているのですか。誰も私にどのようにこれを働かせるか教えてもらえますか? IMHO、可能ならば、そうでなければprepend
もコンパイルされないだろうから。おそらくthisのようなトリックが役立ちますか? (しかし、それを理解していない)。
PS:コードをFsSnipに貼り付けて、ブラウザで再生することもできます。
ディープ第2項目は '2-3フィンガーツリー>は'と 'viewl'が' 'A'は 'ノード<'a>なければならないことを意味する' 2-3フィンガーツリー<'a> 'を取ります'それではエラーメッセージ –
Sehnsucht
@Sehnsucht:しかし、' prepend'の注釈のいずれかを削除するとき、私は同じエラーを受け取ります。すべてのツリーレベルには実際に独自のタイプがあるので、同じ推論がそこに保持されます。しかし、あなたはそれを動作させることができます。 – primfaktor