我希望能够做到
let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast
然而,然后限制'T为'TResult而不是它可以被投射到的东西'TResult
我知道我可以
|> fun x -> x :> 'TResult
|> fun x -> upcast x
|> fun x -> x :> _
但当时如果我做什么都在该行我要回去,并把()周围的fun x -> upcast x或它认为我在做什么是的一部分fun x功能.
我可以定义或存在一种方法可以
|> upcast |> 不起作用
|> ( ( :> ) 'TResult) 不起作用,而且很乱
编辑 回应Thomas Petricek - 最小失败的自动翻译样本:
module Test =
let inline f'<'t>():IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> fun x -> x :> IReadOnlyCollection<_>
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
Run Code Online (Sandbox Code Playgroud)
据我所知,指定一种约束之间的'T和'TResult是不可能的.有一个相关的问题,包括更多信息和功能请求的链接.
那就是说,我想知道你为什么需要这个?F#编译器能够自动插入向上转换,即使在使用管道时也是如此,因此如果要将其作为较长管道的一部分进行,则不需要它.这是一个简单的说明:
type Animal = interface end
type Dog = inherit Animal
let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0
makeDog () |> consumeAnimal
Run Code Online (Sandbox Code Playgroud)
我想如果你想在管道末端拥有它,你可能需要可管道的upcast,但是我只是在另一条线上进行upcast.或者你的问题是由一些更复杂的情况所驱动的,其中隐式上传不起作用?
编辑1:这是一个使用的最小例子ReadOnlyCollection,IReadOnlyList它起作用:
let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0
foo() |> bar
Run Code Online (Sandbox Code Playgroud)
编辑2:评论更新 - 这里的问题是仅在向函数传递参数时插入自动向上转换,但在第二个示例中,类型不匹配在管道的结果和函数的返回类型之间.您可以通过IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>在管道末尾添加类型的标识函数来实现此目的:
let inline f<'t> () :IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
|> id<IReadOnlyCollection<_>>
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为现在在将参数传递给id函数时自动插入upcast - 然后返回与函数的返回类型匹配的类型.
更简单和出乎意料
let inline f2<'t>() : IReadOnlyCollection<'t> =
List.empty
|> ResizeArray
|> System.Collections.ObjectModel.ReadOnlyCollection
:> _
Run Code Online (Sandbox Code Playgroud)