是否已经存在,或者我可以宣布更友好的管道?

时间:2018-11-08 18:39:13

标签: 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周围,否则它会认为我正在做的事情是{{1}的一部分}功能。

我可以定义还是存在一种方法来

fun x不起作用

|> upcast |>不起作用,而且混乱

编辑 作为对Thomas Petricek的回应-最少失败的自动上传示例:

|> ( ( :> ) 'TResult)

2 个答案:

答案 0 :(得分:5)

据我所知,不可能指定'T'TResult之间的约束类型。有一个相关的question about this,其中包含指向更多信息和功能请求的链接。

那是说,我不知道你为什么需要这个? F#编译器即使在使用管道时也能够自动插入上流,因此,如果您希望将其作为较长管道的一部分来执行,则不需要。这是一个简单的例子:

type Animal = interface end
type Dog = inherit Animal 

let makeDog () = { new Dog }
let consumeAnimal (a:Animal) = 0

makeDog () |> consumeAnimal

我想,如果您想在管道的末尾进行管道传输,可能需要管道传输,但是我只是在另一行进行传输。还是您的问题是由一些更复杂的情况引起的,其中隐含的上行链路不起作用?

编辑1:这是一个使用ReadOnlyCollectionIReadOnlyList的最小示例,该示例有效:

let foo () : System.Collections.ObjectModel.ReadOnlyCollection<int> = failwith "!"
let bar (x:System.Collections.Generic.IReadOnlyList<int>) = 0

foo() |> bar

编辑2:要对更新进行评论-这里的问题是,仅在将参数传递给函数时才插入自动上播,但是在第二个示例中,类型不匹配是在结果之间管道和函数的返回类型。您可以通过在管道末尾添加IReadOnlyCollection<'T> -> IReadOnlyCollection<'T>类型的标识函数来使其工作:

let inline f<'t> () :IReadOnlyCollection<'t> =
    List.empty
    |> ResizeArray
    |> System.Collections.ObjectModel.ReadOnlyCollection
    |> id<IReadOnlyCollection<_>>

之所以可行,是因为现在将参数传递给id函数时会自动插入upcast,然后返回与该函数的返回类型匹配的类型。

答案 1 :(得分:0)

更加简单和意外

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