为什么需要类型注释?

时间:2015-11-20 14:18:50

标签: f#

此功能具有签名: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 来解决此问题)

2 个答案:

答案 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,然后让类型推断完成它。