F#をより良くし、Suave.ioの動作をよりよく理解するために、関数を作成するための再利用可能な関数/演算子を作成しようとしています。私はSuaveが> =>演算子を実際に実装して非同期オプションとして動作することを理解していますが、一般化しようとすると楽しいと思いました。静的に解決された型メンバの制約がシステム型の増補を認識しない
以下のコードは、あまりにも多くの情報源から影響を受けています。自分で定義した型ではうまくいきますが、システム型では機能しません。 NullableとOptionの型補完はうまくコンパイルされますが、bind関数のメンバ制約と一致するとは認識されません。
私がOptionで動作させなかったとき、F#で特別なオプションが原因である可能性があるので、Nullableで試してみましたが、悲しいことに葉巻はありませんでした。
fsiからの関連するエラーと出力は、コメントの下のコードにあります。
ご協力いただければ幸いです。
おかげで、 ジョン
open System
let inline bind (f : ^f) (v : ^v) =
(^v : (static member doBind : ^f * ^v -> ^r)(f, v))
// I'd prefer not having to use a tuple in doBind, but I've
// been unable to make multi arg member constraint work
let inline (>=>) f g = f >> (bind g)
// Example with Result
type public Result<'a,'b> =
| Success of 'a
| Error of 'b
type public Result<'a,'b> with
static member inline public doBind (f, v) =
match v with
| Success s -> f s
| Error e -> Error e
let rF a = if a > 0 then Success a else Error "less than 0"
let rG a = if a < 10 then Success a else Error "greater than 9"
let rFG = rF >=> rG
// val rFG : (int -> Result<int,string>)
//> rFG 0;;
//val it : Result<int,string> = Error "less than 0"
//> rFG 1;;
//val it : Result<int,string> = Success 1
//> rFG 10;;
//val it : Result<int,string> = Error "greater than 9"
//> rFG 9;;
//val it : Result<int,string> = Success 9
// So it works as expected for Result
// Example with Nullable
type Nullable<'T when 'T: (new : unit -> 'T) and 'T: struct and 'T:> ValueType> with
static member inline public doBind (f, v: Nullable<'T>) =
if v.HasValue then f v.Value else Nullable()
let nF a = if a > 0 then Nullable a else Nullable()
let nG a = if a < 10 then Nullable a else Nullable()
let nFG = nF >=> nG
// error FS0001: The type 'Nullable<int>' does not support the operator 'doBind'
type Core.Option<'T> with
static member inline doBind (f, v) =
match v with
| Some s -> f s
| None -> None
let oF a = if a > 0 then Some a else None
let oG a = if a < 10 then Some a else None
let oFG = oF >=> oG
// error FS0001: The type 'int option' does not support the operator 'doBind'
拡張メンバーは、静的に解決された型制約のために考慮されません。ちょうどF#、期間の特徴ではありません。 [uservoiceに投票してください](https://fslang.uservoice.com/forums/245727-f-language/suggestions/5664242-simulate-higher-kinded-polymorphism)。 –
Fyodorが述べたように、これはサポートされていません。これは実際にF#のすばらしい拡張だと思うが、私はあなたがこれについてどのようなユースケースを思いついたのかなんて不思議だ。私はSuaveがとてもシンプルで、あまり抽象的ではないので、オペレータを一般化するとF#コードが改善されるようには聞こえません。 –
@FyodorSoikinありがとう、それはそれを説明します。どのような迷惑な制限、3票がキャストされました:) – JJJ