なぜ

2012-08-23 4 views
6

F#の型宣言の重要な括弧は次のとおりです。なぜ

Microsoft (R) F# 2.0 Interactive build 4.0.40219.1 
Copyright (c) Microsoft Corporation. All Rights Reserved. 

For help type #help;; 

> type foo = Foo of (string * int);; 
    type foo = | Foo of (string * int) 

> let f = Foo ("bar",42);; 
    val f : foo = Foo ("bar", 42) 

> match f with Foo x -> x;; 
    val it : string * int = ("bar", 42) 

> type bar = Bar of string * int;; 
    type bar = | Bar of string * int 

> let b = Bar ("baz",21);; 
    val b : bar = Bar ("baz",21) 

> match b with Bar x -> x;; 
    match b with Bar x -> x;; 
    -------------^^^^^ 

stdin(7,14): error FS0019: This constructor is applied to 1 argument(s) but expects 2 
> 

これは、両方のFooに一致するそのパターン私には明らかと思われます1つの変数を持つBarが有効である必要があります。だから、誰かがこの奇妙な振る舞いの理由を知っていたのか、あなたが私を好きなのであればそれをバグだと思っています。

更新: だけ明確にする、コンストラクタFooBarの報告タイプは次のとおりです。

> Foo;; 
val it : string * int -> foo = <fun:[email protected]> 
> Bar;; 
val it : string * int -> bar = <fun:[email protected]> 

確かに、彼らは有効なパターンの同じセットに

答えて

6

を受け入れるべきだから私は、これはかなり見え同意混乱する。パッドが説明したように、2つの宣言の違いは構文的なものではなく、実際には異なるタイプからなる区別されたユニオンのケースを定義しています。 Fooの場合

  • は、ケースがBarの場合種類int * string
  • の一つの要素が含まれ、ケースは、2つのタイプintの要素とstring

を含有する2つのオプションは、非常に類似しています実際には違っています。 the type definitions in the F# specificationを見ると分かります。

組合型-DEFN:ここでは、判別共用体の型定義を記述するためのビットです=
   タイプ名 '=' ユニオン・タイプのケース型の拡張要素は

を選びます

ユニオンタイプのケース:=
    '|' optユニオンタイプのケース '|' ...'|'ユニオン型ケース

組合型の場合:=
   

組合型の場合、データオプト  組合型ケース・データを属性:=
   のident                                                                     - nullの組合の場合
   タイプ* ... *タイプのIDENT           - N-アリユニオンケース

"n-ary union case"は複数の要素(type * ... * type)で構成されています。

タイプ:(驚くことではないが、それができるタプル)は、以下のようにタイプが定義されている=
   (タイプ)
   タイプ - >型              - 機能タイプ
   タイプ* ... *タイプ      - タプルタイプ
    ...                                                 - 他のタイプの多く

私はなぜか分からないユニオンタイプのケースデータは単項式の大文字小文字を使用するのではなく(n-aryの代わりに)、要素を常にタプルとして扱います。私はそれが理にかなっていると思うが、それはF#がOCamlやMLから継承したものかもしれない。しかし、少なくとも仕様ではこれが説明されています!

実際には、Foo of int * intをn-aryユニオンのケースとタプルの単項ケースの両方として扱うことができるため、仕様は少し曖昧です(ブラケット付きタイプ(type)はありません)。

+0

非常に徹底的な回答をいただきありがとうございます。また、関連する言語仕様を指摘していただきありがとうございます。しかし、私はそれが意図的だったことを今、さらに深刻な怪物と考えているのではないかと恐れています! :-) – plc

+1

@plc - 私は違いの理由は、C#のような他の言語とのinteropの境界を制御することだと思うだろう。その場合は、あらかじめ作成されたタプルを渡すか、構成項目を個別に渡すことによってDUインスタンスを作成する必要があるかどうかを気にする必要があります。 – kvb