2016-09-06 61 views
2
type FFRec<'state when 'state: (member Tape: Stack<unit -> unit>) 
        and 'state: (member Mem: ObjectPool) 
        and 'state: (member Str: CudaStream) 
        and 'state: (member Workspace: Workspace) 
        and 'state: (member IsInferenceOnly: bool)> = 
    { 
    W: d2M 
    b: d2M 
    a: d2M -> 'state -> d2M * 'state 
    } 

有可能與接口全部更換這些成員的約束,但一個小問題,這種方法是編譯器沒有足夠的智慧認識到,如果我有這樣的函數,例如:是否可以使用成員約束進行類型縮寫?

let inline reluInitializer (state: ^state) (a: ^a) = 
    let scale = (1.0f/sqrt(addDims a |> float32)) 
    fillRandomUniformMatrix((str state),a,scale,0.0f) 
    a 

它不會意識到^state將不得不有一個接口約束,並給我一個莫名的簽名和實現不同的錯誤記錄通用參數聲明。

如果完全可能我寧願使用成員約束而不是顯式接口,但我找不到使用類型縮寫來縮短上述約束聲明的方法。這在當前的F#中可能嗎?

+0

查看關鍵字'inline'。這是F#對你想要做的最好的近似。 – asibahi

回答

4

不,不可能在類型中使用靜態解析的類型參數。

CLR不支持靜態解析的類型參數,因此需要在編譯時擦除。這可以通過在調用站點內聯一個函數來完成,而不是將它編譯到IL,但是一個類型必須有一個IL表示,因爲否則在運行時你不能擁有它的實例。

你應該考慮以評估員職能的形式表達你的約束,每個成員一個。這樣,即使你的類型會用「不可接受的」類型的參數進行編譯,它的用法也不會,從而有效地限制了整個程序。

至於你在你的例子中用^state參數描述的問題,我不太明白它是什麼:你的函數沒有任何成員訪問權限,所以我不明白它是如何引起的與成員有關的錯誤。


並在評論中回答您的問題:不,不可以在類型別名中包含成員約束以便重用。

+0

如果通過訪問函數,你指的是內聯函數的類型,例如'let inline dispose v =(^ b:(member Dispose:unit - > unit)v)'然後我將它們遍佈整個地方。我上面顯示的只是我的2k LOC庫的一小部分,所以我不確定是否需要顯示實現。與常規的let函數不同,編譯器要求我在類和記錄中明確地寫出成員約束,而不是自己推斷它們,所以我確實在問是否可以縮寫類型約束。 –

+0

現在我正在嘗試使用繼承來實現它,並且在使用繼承約束時會遇到真正無用的類型錯誤。基本上,整個庫是內聯的,並使用靜態解析類型參數以簡化。 –

+1

你沒有讓你的問題或問題更清楚。嘗試更具體。嘗試提供示例以及所需的結果和錯誤消息。 –

相關問題