Can a function of type (unit -> unit) have statically resolved type parameters in F#?

醉酒当歌 提交于 2019-12-11 04:55:32

问题


Why isn't this allowed?

type Foo() =
    static member Bar() = ()

let inline bar<^a>() = //ERROR: unexpected infix operator in pattern
    (^a : (static member Bar : unit -> unit)())

//Hypothetical usage: let _ = bar<Foo>()

...but this works fine?

type Foo() =
    static member Bar() = new Foo()

let inline bar() : ^a =
    (^a : (static member Bar : unit -> ^a)())

let x : Foo = bar()

Are functions with statically resolved type parameters required to return an instance of the resolved type?


回答1:


As you noticed, F# treats the sequence of characters <^ as an infix operator, so you need to separate them with a space. As to the question of when you need to explicitly specify constraints, I believe that the rule is that when you explicitly give a function type parameters then you also need to specify any necessary constraints. Otherwise, if F# can infer the type parameters and constraints, you don't need to specify them.

So this example from your question works fine:

let inline bar() :^a =
  (^a : (static member Bar : unit -> ^a)())

as would this:

let inline bar(x : ^a) =
  (^a : (static member Bar : unit -> unit)())

because there's a generic type parameter, but you haven't explicitly placed it on the function, and F# can infer the needed constraint.

On the other hand, if you try to modify your other example to omit the explicit generic parameter:

let inline bar() =
  (^a : (static member Bar : unit -> unit)())

You'll see that F# won't allow this because there's no way for it to figure out how to instantiate ^a for any given call of bar(). Thus, you need to provide the type parameter explicitly, and once you do, you also have to explicitly provide the constraint.




回答2:


Figured it out. Spaces inside the angle brackets are needed, along with a constraint.

This works:

type Foo() =
    static member Bar() = ()

let inline bar< ^a when ^a : (static member Bar : unit -> unit) >() =
    (^a : (static member Bar : unit -> unit)())

let _ = bar<Foo>()

From this we can surmise that the constraint is optional if the function returns an instance of the statically resolved type. Does anyone know if that's the rule?



来源:https://stackoverflow.com/questions/2150701/can-a-function-of-type-unit-unit-have-statically-resolved-type-parameters-i

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!