I suppose there is three ways to do that:

  • by using interface with those functions declared for all your objects you want to use with doSomeWork (worker :> Iface)
  • by using .net reflection mechanics
  • by using abstract type wrapper:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type test =
  { a: int }
  member o.f1() = printfn "a: %d" (1+o.a)
  member o.f2() = printfn "a: %d" (2+o.a)

type wrapper<'a> =
  {
    f1: ('a -> unit);
    f2: ('a -> unit);
  }

let doSomeWork (w: wrapper<'a>) =
  w.f1()
  w.f2()

let x = { a = 0 }
doSomeWork { f1 = x.f1;  f2 = x.f2 }
By on 7/19/2008 9:59 PM ()

All these solutions look like some workaround for initial problem.

1)With interface we can't use class which implement all required methods but don't have required interface reference.
2) Reflection have lack of type checking in compile time
3) Wrapper look slightly ugly.

In OCaml I can write next equivalent:

1
2
3
let doWork worker:<work1:unit ->unit; work2:unit->unit; ..> =
        worker#work1()
        worker#work2()

Does it possible write similar constrain in F# without using interface?

By on 7/19/2008 11:35 PM ()

Yes, i agree, those cases are workarounds.
We don't have that constraint but we have all those workarounds and we have object expressions to add interface to object inplace.
P.S. What task do you solve? I've used that constrain for my OCaml code only for case where i'm prototype C++ code heavly templatized by concepts.

By on 7/20/2008 10:12 AM ()

I write some web service. I create two interfaces for access to this service using WCF based service and ASP.NET based web service.

For client I create two proxy class using svcutil.exe and wsdl.exe tools. Both proxy clients class have simmilar sets of methods. On client side manager may be connected to several clients based on both WCF or ASP.NET WS, so I want use generic code which receive proxy object and communicate with any webservice.

By on 7/20/2008 11:43 AM ()

Hi,

F# has a nominal type system, and you can't get structural typing like in OCaml or C++ (through templates). You should try to use one of ssp workarounds.

If you really can't use this worarounds, here's a solution. It uses inlining to get something like C++ templates (but it's less powerful). This might be deprecated in a future release, and you might have some difficulties if your workers have many methods.

I tried my code on this following types:

1
2
3
4
5
6
7
8
9
10
11
12
13
type Foo() =

  member x.work1(x) = printfn "Foo work1 %d" x

  member x.work2(x) = printfn "Foo work2 %d" x


type Bar() =

  member x.work1(x) = printfn "Bar work1 %d" x

  member x.work2(x) = printfn "Bar work2 %d" x

Here it is:

1
2
3
4
5
6
let inline work1 x y = (^a: (member work1 : int -> unit) (x, y))
let inline work2 x y = (^a: (member work2 : int -> unit) (x, y))

let inline doSomeWork worker =
  work1 worker 2
  work2 worker 10

This function is well-typed (statically). Look:

1
2
3
4
val inline doSomeWork :
   ^a -> unit
    when  ^a : (member work1 :  ^a * int -> unit) and
          ^a : (member work2 :  ^a * int -> unit)
By on 7/20/2008 2:54 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper