2016-06-14 17 views
6

結果の型と関数の書込みに慣れていて、説明できない型の不一致のエラーが発生しました。それは正しくコンパイル、あなたはは、以下による関数を適用変更した場合結果の型の型の不一致エラー

init.fsx(8,31): error FS0001: Type mismatch. Expecting a 
('a,'b) result 
but given a 
(('c -> 'a),'d) result 
The resulting type would be infinite when unifying ''a' and ''b -> 'a' 

let apply fr xr = 
    match fr, xr with 
    | Success f, Success x -> Success (f x) 
    | Failure a, Success _ -> Failure a 
    | Success _, Failure b -> Failure b 
    | Failure a, Failure b -> Failure (List.concat [a; b]) 

type ('a, 'b) result = 
    | Success of 'a 
    | Failure of 'b list 

let apply fr xr = 
    match fr, xr with 
    | Success f, Success x -> Success (f x) 
    | Failure _, Success _ -> fr 
    | Success _, Failure _ -> xr 
    | Failure a, Failure b -> Failure (List.concat [a; b]) 

このコードをコンパイルすると、次のエラーを生成します。ここでは最小の例であります

なぜマッチした値を使用するのですか(ここではfrまたはxr)は動作しませんが、新規作成する失敗値はありますか?

答えて

4

を成功タイプは今、関数の結果であるという事実を使用することができる新しいタイプを与えるとは対照的に

、差別化された組合のすべての事件に関係する。戻り値としてすべて戻り値、Successの場合を含む関数パラメータからFailureのインスタンスを「唯一」再利用した場合は、このパラメータと同じ型を持つ必要があります。

したがって、戻り値としてfrxrを使用すると、その型はapplyの戻り値の型と同じになります。

しかし、Success fというパラメータを返す値の行には、Success (f x)という値があります。これらの2つのタイプが同じタイプの場合は、f xのタイプはfのタイプでなければなりません!それは何度もそれを適用しても、それ自身の型の関数を返す関数です。このような無限型は許可されず、コンパイラエラーが発生します。

戻り値の新しいインスタンスを構築することにより、applyの戻り値の型がその型の型と異なることができます。コンパイラは、fとその戻り値に異なる型を与え、無限関数型を避けることができます。

2

ここがエラーです。この行で

Success f, Success x -> Success (f x) 

あなたが関数の型であることを'aを定義し、その結果として、あなたのリターン'aも機能です。

いますが、

| Failure _, Success _ -> fr 

を行うときに、このfrは同じ関数型を持っているが、ここでは未適用です。新しいオブジェクトを作成すると、それをここで理解するための重要な事はタイプということである第二の場合には

+0

ありがとうございました。なぜ最初の試合代替の理由がわからないのですか? '|成功は、X、F成功 - >成功(F x) 'は が第二試合の代替 '上の任意のベアリングを持っている必要があります|失敗_、成功_ - > fr'で が – dumetrulo

+0

問題は 'fr'では'成功(FX)に異なった型を持つ 'と表現が持つ変数を返す必要があるということです...コンパイラにおける不要な制限のように私には聞こえ同じタイプ。 –