此功能具有签名:let private findCase<'T> f =
match FSharpType.GetUnionCases typeof<'T> |> Array.filter f with
|[|case|] -> Some (FSharpValue.MakeUnion(case,[||]) :?> 'T)
|_ -> None
int -> obj
此函数调用上述函数,具有签名:let CreateFromId<'T> id =
match findCase (fun case -> case.Tag = id) with
| Some c -> c
| None -> failwith (sprintf "Lookup for union case by \"%d\" failed." id)
CreateFromId
在c
的模式中,intellisense显示obj
被推断为findCase
类型,即使它显示CreateFromId
的正确签名。为什么这种类型似乎已经失去了#34;在模式中?
(我可以通过将'T
的返回类型指定为$pdf = new FPDI();
$pagecount = $pdf->setSourceFile('../pdf/source-brochure.pdf');
// Add the Cover
$tplCover = $pdf->importPage($cover_versie, '/MediaBox');
$pdf->addPage();
$pdf->useTemplate($tplCover, 0, 0, 210);
$pdf->Image($newFile, $baseOffsetX, $baseOffsetY);
$cover_versie; // Outputs the integer 1, 2, 3, 4 or 5 for the covers
$newFile; // Is the uploaded logo resised and uploaded to the server
来解决此问题)
答案 0 :(得分:1)
由于类型参数'T
未在函数体中引用,因此类型推断无法知道您的意图是将'T
命名为返回类型。
所以你可以把它作为返回类型添加到正文中(正如你已经想到的那样)或者从声明中删除它:
let CreateFromId id = ...
删除它是有效的,因为F#会自动泛化,唯一不同的是它会为类型变量使用任意名称,但即使你想要命名那个类型变量,我要做的就是添加它作为返回类型但在括号内的声明中没有:
let CreateFromId id : 'T = ...
答案 1 :(得分:0)
CreateFromId
的类型由int -> obj
推断,因为没有&#34;链接&#34;函数中的两个'T
类型参数。
findCase
在'T
上是通用的,但CreateFromId
仅被声明为通用,并且从不使用泛型类型参数。
使用所需类型注释函数足以使类型排成一行。您也可以致电findCase
明确提供类型:
let CreateFromId<'T> id =
match findCase<'T> (fun case -> case.Tag = id) with
| Some c -> c
| None -> failwith (sprintf "Lookup for union case by \"%d\" failed." id)
或者正如另一个答案所示,只需从'T
中删除CreateFromId
,然后让类型推断完成它。