2017-09-26 11 views
3

を働いていない注釈を入力します。F#関数の引数は、私はF#関数で引数の特定のタイプを持ちたい

type NewType = string*int 

let testFunction (arg1:NewType) : NewType = 
    ("resultString", 2) 

testFunction ("test", 3) 

私は関数の型になりたい:

NewType -> NewType 

しかし、関数型は次のとおりです。

string*int -> NewType 

引数arg1の型を "NewType"にするにはどうすればよいですか?

答えて

4

type NewType = string * intはタイプの略語と呼ばれるものです。別のタイプに名前やエイリアスを付けますが、コンパイル時に消去されます。カプセル化はなく、新しいリファレンスも基本的に新しいタイプもありません。

これはドキュメントとして機能しますが、F#のコンパイラは新しい名前とエイリアスタイプを同じものとして扱います。これは、NewTypeを使用する公開関数/メソッドを持つDLLを作成し、別のプロジェクトから呼び出しようとすると特に見えます。あなたの場合のように混合結果が表示されます。

これは、達成したいことが読みやすくするためには問題ではないかもしれません。コード内にlet testFunction (arg1:NewType) : NewType = ...が表示されている場合、特にIntelliSenseのツールチップがないGitHubのようなWeb上では、実際に「実際」のタイプがであっても、関数が受け取った戻り値がかなりわかります。

は、あなたがより良い型の安全性が必要な場合は、通常の練習は、シングルケースを定義しているあなたは、パターンは次のように一致して組み合わせることができ組合を区別:

type NewType = NewType of (string * int) 

let testFunction (NewType arg1): NewType = 
    NewType ("resultString", 2) 

testFunction (NewType ("test", 3)) 

あなたがよりここに読み、そしてからの他の記事にすることができますシリーズ:https://fsharpforfunandprofit.com/posts/type-abbreviations/

+1

しかし、なぜ戻り値の型は "NewType"ですか、それは戻り値の型ではなく、引数では機能しません。ところでリンクのおかげで! – FraK

+1

@FraK、これは良い質問です。それ以外の満足できる答えはわかりません。それはコンパイラの現在のバージョンがどうやってそれを行うのかです(例:https://github.com/fsharp/fsharp/issues/717)。 Tomasがきちんと書いたように、元の型とそのエイリアスはコンパイラ(と他のツーリング)のために互換性があり、どちらが見えるかは保証されません。 –

+0

答えをありがとう – FraK

4

NewTypeの型宣言はNewTypestring * intと交換可能であることを意味し、タイプの別名です - コンパイラは同じものとして扱い、時にはこれは型注釈を持つにもかかわらず、他の場所で1を報告することを意味します。

フルネームで常に参照する必要のあるタイプを希望する場合は、それを明示的な新しいタイプとして定義する必要があります。この時点では、レコードを使用することが最善の方法ですあなたは)個々のフィールドに名前を付けるが、あなたは簡潔な何かをしたい場合は、代わりにシングルケース区別組合を使用することができます。

type NewType = NT of (string*int) 

let testFunction (NT arg1) : NewType = 
    NT("resultString", 2) 

testFunction (NT("test", 3)) 
+0

しかし、なぜ戻り値の型は常に働くのですか?それは "NewType"で、文字列* intではないのですか? – FraK

+0

@FraKコンパイラのいくつかの実装の詳細の単なる副作用だと思います。コンパイラは、 't1'と' t2'の2つの型を統一するとコンパイラはそれらが等しいかどうかをチェックし、それが示すタイプ名。 –

+0

答えをありがとう – FraK