Take the 2-minute tour ×

Hi the following example (Simplified) is retrieved by an application that I'm implementing which uses consistently Type Parameters resolved statically.

type A< ^B when ^B : (static member MyMember : Unit -> Unit)> = {
  Field : unit
type TestA = {
  AField : A< BTy >
and BTy = {
  BField : Unit
} with
  static member MyMember () = ()

Well the intellisense gives me the following error when i define the type of field AField (AField : A< BTy >) which is: The type 'BTy' does not support any operators named 'MyMember'.

EDITED. Declare them separetly works, but if i have a mutual reference and i cannot declare a third type to put in the top which containts the common Infos of the two types, what i should do to avoid this problem? Anyway if i define below the definitions let pluto = ("" :> obj) :?> A< BTy > it work's, i imagine bacuase both the types are visible from the let binding.

share|improve this question
Are these sorts of constraints even allowable? This could cause all sorts of problems for interop as say the C# compiler can't implement them. Also, from the docs page Cannot be used on types. for statically resolved. –  John Palmer Oct 14 '12 at 11:48
Is there any reason not to declare them separately? E.g, type A, then type BTy, then type TestA? –  bytebuster Oct 14 '12 at 11:49
@JohnPalmer static member constraints are listed on MSDN as a valid example –  bytebuster Oct 14 '12 at 11:53
bytebuster is right. Recursive type declaration doesn't play nicely with static constraints. Put your declarations in order; it would work. –  pad Oct 14 '12 at 12:17
@bytebuster - but check the statically resolved page msdn.microsoft.com/en-us/library/dd548046.aspx - it says cannot be used on types –  John Palmer Oct 14 '12 at 21:08
add comment

2 Answers

To be honest, I'm a bit surprised that you are even allowed to use static member constraints in a type declaration, but as mentioned by @pad, when you put the declarations in the right order and remove the recursion, it works (although I'm not sure that there won't be other limitations when you move to more complex examples):

  { Field : unit } 

type BTy = 
  { BField : Unit } 
  static member MyMember () = () 

type TestA = { AField : A<BTy> }

Anyway, I think using static member constraints in a type declaration is a bit complicated. A cleaner way to do this would be to define an interface that clearly describes (and documents) the members you need:

type IMyMember =
  abstract MyMember : unit -> unit

Now, static member constraints can still be used to create an implementation of the interface from a type that has the required member, but does not implement the interface. Using this technique, you should be able to implement exactly the same functionality as with static member constraints on types (but in a clearer way):

/// Captures 'IMyMember' implementation from another type using static constraints
let inline captureMyMember< ^B when ^B : (static member MyMember : Unit -> Unit)> =
  { new IMyMember with
      member x.MyMember () = 
        (^B : (static member MyMember : Unit -> Unit) ()) }

The function will, for example, create IMyMember from your BTy type:

/// A type that contains field and a captured implementation of 'IMyMember'
type A = 
  { Field : unit 
    Operations : IMyMember } 

let it = { Field = ()
           Operations = captureMyMember<BTy> }

Aside, I used the same technique in an article that shows how to write generic numeric code and I think that it worked there really nicely.

share|improve this answer
add comment
up vote 0 down vote accepted

Your implementation @Tomas satisfies the question but there is some hesitation over the style of your solution because it does not respected the functional programming paradigm. I thought to a solution arising from the Type Classes implementation of Haskell. Interfaces, abstract classes, etc. have been implemented in order to allow the F# environment to “interact” with the .Net environment, for a reason of uniformity of style the use of code which implements interfaces, abstract classes etc. in a context where no need of interact with the .Net libraries, it is a “Overhead” in my opinion (although F# is a multi-paradigm language). This is the reason why I found the implementation of the Type Classes of Haskell very elegant. Below I implemented through F# the “Haskell Type Class” code to solve my problem.

type Operations< ^a> = 
    MyMember : unit -> unit

type A< ^a> = {
  Operations : Operations< ^a>

and TestA = { 
  AField : A< BTy > 

and BTy = { 
  BField : Unit 

let it = 
  let BTy_operations : Operations< BTy > = { MyMember = fun () -> () }
  let A_of_BTy = { Operations = BTy_operations }
  { AField = A_of_BTy }
share|improve this answer
This looks like a fine solution too. It requires more typing than implementation that captures MyMember implementation using static constraints (you'd have to fill the implementation in BTy_operations), which I thought was the point of your question. –  Tomas Petricek Oct 22 '12 at 13:07
But keep in mind that F# is not Haskell. F# is a multi-paradigm langauge and it is designed to allow mixing object-oriented concepts like interfaces with functional concepts like records when it makes sense. F# does not support Haskell-style type classes and so people use different programming patterns to solve problems that you'd solve using type classes in Haskell. Trying to mimick solution that works in Haskell will not give you idiomatic F# code. –  Tomas Petricek Oct 22 '12 at 13:08
add comment

Your Answer


