Hello.

Maybe you can do something with objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type 'a t = class
  val mutable data: 'a list
  new () = { data = [] }
  member self.push elm = self.data <- (elm :: self.data)
  member self.pop () = 
    let hd = List.hd self.data in self.data <- List.tl self.data; hd
end;;

//type 'a t = class
//              val mutable data: 'a list
//            end
//            with
//              new : unit -> 'a t
//              member pop : unit -> 'a
//              member push : elm:'a -> unit
//            end

With best regards,
Keiko

By on 1/16/2008 8:55 AM ()

Hello.

Maybe you can do something with objects.

Well, I'm not just implementing Stack, I'm trying to write a function to accept any possible implementation(representation) of Stack (Here you use "list" as representation, but it could be others).

By on 1/17/2008 1:22 AM ()

Hello.

Sorry for my jumping to the wrong direction.

I am interested in the problem you have
and would like to understand the situation and the possible solutions.

Is it impossible or too cumbersome to use nested function definitions?
In some sense, functors are a modular way of doing so.
(I hope I have not jumped into another wrong pond...)

My real example has a few contracts corelated,
I'm afraid the encoding would be a bit complex.

It would be nice for me if you could expand on your example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
type IStack<'a> = interface
  abstract push: 'a -> unit
  abstract pop: unit -> 'a
end;;


// a factory for grouping relevant static methods 
type IFactory<'a,'b when 'b :> IStack<'a>> = interface
 abstract create: unit -> 'b
 abstract combine: 'b -> 'b -> 'b
end;;


// This is close in spirits to 
// functor(X : sig val create: ... end) -> struct let of_list = ... let compose end 
// In general, wrapper will return a n-tuple of functions. 
let wrapper (f:#IFactory<'a,'b>) = 
  let of_list comps = 
    let o = f.create () in
    let rec iter = function [] -> () | hd :: tl -> o.push hd; iter tl in
    iter comps; o in 
  let compose = fun comps1 -> fun comps2 -> f.combine (of_list comps1) (of_list comps2) in
  compose;;


// to check the above setting works ....
type Stack<'a> = class
  val mutable data: 'a list
  new () = { data = [] }
  interface IStack<'a> with 
    member self.push elm = self.data <- (elm :: self.data)
    member self.pop () = 
      let hd = List.hd self.data in self.data <- List.tl self.data; hd
  end
end;;


type ListFactory = class
  new () = {} 
  interface IFactory<int, Stack<int>> with
    member self.create () = new Stack<int> ()
    member self.combine (d1: Stack<int>) (d2: Stack<int>) = 
      let o = new Stack<int> () in o.data <- (List.append d1.data d2.data); o
  end
end;;


let wrapper_list = wrapper (new ListFactory ());;

With best regards,
Keiko

By on 1/18/2008 5:16 AM ()

Hi

It would be nice for me if you could expand on your example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type IStack<'a> = interface
  abstract push: 'a -> unit
  abstract pop: unit -> 'a
end;;


// a factory for grouping relevant static methods 
type IFactory<'a,'b when 'b :> IStack<'a>> = interface
 abstract create: unit -> 'b
 abstract combine: 'b -> 'b -> 'b
end;;


// This is close in spirits to 
// functor(X : sig val create: ... end) -> struct let of_list = ... let compose end 
// In general, wrapper will return a n-tuple of functions. 
let wrapper (f:#IFactory<'a,'b>) = 
  let of_list comps = 
    let o = f.create () in
    let rec iter = function [] -> () | hd :: tl -> o.push hd; iter tl in
    iter comps; o in 
  let compose = fun comps1 -> fun comps2 -> f.combine (of_list comps1) (of_list comps2) in
  compose;;

Thanks for the reply. This is pretty much the same solution I took so far, still it's nice of you to post the full encoding of the example for the reference of everyone here.

Cheers
d2bg

By on 1/18/2008 6:15 AM ()

One solution is to use an interface type:

1
2
3
type IStack<'a> = 
   abstract push: 'a -> unit
   abstract pop: unit -> 'a

and pass around the "create" function

1
let f (create: unit -> IStack<'a>) = ...

Kind regards

don

By on 1/16/2008 5:45 PM ()

One solution is to use an interface type:

1
2
3
type IStack<'a> = 
   abstract push: 'a -> unit
   abstract pop: unit -> 'a

and pass around the "create" function

1
let f (create: unit -> IStack<'a>) = ...

Hi Don,

Thanks for the suggestion. On one hand, interface has something in common with functor and does work well in some cases; on the other hand, I still feel some limitations. In particular, does it means I have to pass the "new" function and other static functions as arguments instead of defining them as parts of the interface (because I can't see how to do that) ?

Actually, I found it more convenient to define several corelated contracts (interface) to simulate the functor. Still using Stack as an example, should I define another interface like

1
2
3
type IStackAll<'a,'b> when 'a :> IStack<'b> =
    abstract combine: 'a -> 'a -> 'a
    abstract compare: 'a -> 'a -> bool

for the static method etc.

Is it normal? My real example has a few contracts corelated, I'm afraid the encoding would be a bit complex.

By on 1/17/2008 1:54 AM ()

In particular, does it means I have to pass the "new" function and other static functions as arguments instead of defining them as parts of the interface (because I can't see how to do that) ?

Yes, interfaces don't support static members. As a workaround you can sometimes use a default-constructor constraint and implement the static methods as normal methods, but that is extremely ugly.

.Net simply doesn't support natively a generic programming construct that is as powerful as ML functors or C++ templates. Implementing such a feature would require extensive inlining either by the VM or the compiler, which doesn't seem to be very popular among .net implementers.

But do you really need to abstract over the type of the stack?

Best regards,
Stephan

By on 1/17/2008 2:47 AM ()
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