2017-02-01 8 views
11

ように行動していませんF#の型コンストラクタは、私はこのようなタイプを定義する場合、関数

Items [1;2;3] 

をただし、次のようにはありません作品:

[1;2;3] |> Items 

エラーメッセージは次のとおりです。

Type mismatch. Expecting a 
    int list -> 'a  
but given a 
    seq<int> -> Foo 

int listをコンパイラでseq<int>に変換できませんか。 Itemsコンストラクタは通常の関数であった場合、私はどちらかの方法でそれを呼び出すことができます:

let length ints = Seq.length ints 
printfn "%A" (length [1;2;3]) 
printfn "%A" ([1;2;3] |> length) 
+4

コンストラクタをファーストクラスの関数として使用することは、かなり新しい機能です(新しいものではありませんが、それでもなお機能します)。 http://stackoverflow.com/questions/531178/using-the-f-pipe-symbol-with-an-object-constructorを参照してください。これはバグかもしれません。 – mydogisbox

+0

OK。誰かがMicrosoftのF#チームにバグを報告する方法を知っていますか? – brianberns

+1

https://github.com/fsharp/fsharp/issues/new – jpierson

答えて

2

これは、答えよりも推測の詳細ですが、私はコンストラクタができないという問題がC#で同様の動作に関連することができることを疑います型パラメータを持つデフォルトでは、F#関数は完全に汎用であり、型の注釈と推論によってのみ特殊化されると私は理解しています。コンストラクタが型パラメータを持つことができない場合は、CLRまたは.NETに一般的に組み込まれているものであれば、F#型のコンストラクタが、関数に対して行われるのと同じように、このジェネリックに従うことができない場合があります。

+0

私は上記の私の前提は正しいですし、C#でよく使われる同じ回避策がF#で動作して、必要に応じて必要な型引数を持つコンストラクタを呼び出す型の静的ファクトリメソッドを作成する可能性があります。 – jpierson

3

これは共分散問題です。 タイプコンストラクタ関数Itemsseq<int> -> Itemsですが、List<int>が指定されています。これは、F#が自動サブタイプ変換を行わないため明示的にダウンキャストする必要があります。あなたのコードを変更した場合

type Foo = Items of int list 
[1;2;3] |> Items //compiles 

かは、このようになり、関連するモジュール

type Foo = Items of int seq 
[1;2;3] |> Seq.ofList |> Items //compiles 
+2

F#は私が与えた他の例では自動サブタイプ変換を行います。なぜこのケースが異なって振る舞うのか知りたいのですが。 – brianberns

+2

'>タイプFoo = seqの項目 ;; >アイテム;; ヴァルそれ:arg0の:SEQ - >はFoo = <楽しさ:18-5 @ CLO> ' '聞かせて長さ(int型:int型配列)= Seq.length int型 >聞かせて長さ(int型:int型の配列)=アイテムints ;; >長さ;; val it:(seq - > Foo)= ' 同じタイプのシグネチャでも同じ問題です。私はこれがバグだと確信しています。 @mydogisboxが合意した。 – mydogisbox

+0

型推論の問題のために意図的にコンストラクタ関数を厳密に保持していた可能性があります。確認する問題を提起する価値がある。 – Asti

1

を使用します。

> type Foo = Items of seq<int>;; 
> Items;; 
val it : arg0:seq<int> -> Foo = <fun:[email protected]> 

> let length (ints: int seq) = Items ints;; 
> length;; 
val it : (seq<int> -> Foo) = <fun:[email protected]> 

問題が一層顕著になります。ほとんど同じ型署名ですが、それと同じ問題です。私はこれがコンストラクタをファーストクラスの関数として使用しているバグだと確信しています。

+1

良い点。私はこれをバグとして報告しました。彼らの言うことを見てみましょう。 – brianberns

+2

'type Foo = seqの項目 ;; let items =アイテム;; [1; 2; 3] |>アイテム;;も同様に*同じ*です。 –

+1

@NikontheThirdこれは面白い回避策です – mydogisbox

関連する問題