是否已经或者我可以声明更加管道友好的向上翻?

Mas*_*low 6 f#

我希望能够做到

let upcast'<'T,'TResult when 'T :> 'TResult> (y:'T) = y |> upcast

然而,然后限制'T为'TResult而不是它可以被投射到的东西'TResult

我知道我可以

  1. |> fun x -> x :> 'TResult

  2. |> fun x -> upcast x

  3. |> 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)

Tom*_*cek 5

据我所知,指定一种约束之间的'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 - 然后返回与函数的返回类型匹配的类型.


Mas*_*low 1

更简单和出乎意料

let inline f2<'t>() : IReadOnlyCollection<'t> = 
    List.empty
    |> ResizeArray
    |> System.Collections.ObjectModel.ReadOnlyCollection
    :> _
Run Code Online (Sandbox Code Playgroud)