Hi Sadek,

Does this fit the bill?

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
49
50
51
52
53
54
55
56
57
58
#light

(* type decls *)

type Gender = Male | Female

and Person  = {
  name     : string;
  gender   : Gender;
  children : Person list
}

let person n g children = 
  { 
    name     = n;
    gender   = g;
    children = children
  }

let personWithNoChildrenYet n g =
  { 
    name     = n;
    gender   = g;
    children = list.Empty
  }


(* typeclass *)
type T<'a> = { T : 'a -> Person list -> Person }

module TInstances = 
  (* instance 1 *)
  let f1 : T<(Person list -> Person)> = { T = id } in

  (* instance 2 *)
  let f2 : T = 
    { T = fun person children -> 
        { person with 
            children = person.children @ children }} in
    
  (* this dispatch function can be autogenerated *)
  let fx<'x> : T<'x> = 
    if typeof<'x> = typeof then
      (unbox (box f2))
    else if typeof<'x> = typeof<(Person list -> Person)> then
      (unbox (box f1))
    else failwith "?"

(* ad-hoc polymorphic function *)
let (>>) (a : 'a) = TInstances.fx<'a>.T a

(* examples of use *)

let marta = { name = "Marta"; gender = Female; children = [] }
let bob   = { name = "Bob";   gender = Male;   children = [] }

(marta >> [bob])                      |> printfn "%A" 
((person "abe" Male) >> [marta; bob]) |> printfn "%A"

It is most likely a very bad way to do what you want, but this programming style is possible, if you are willing to pay the price. I see your use of (++) - do you by chance speak any Haskell? :) If not, I encourage you to read up on type classes, and then on their emulation in F# (Kurt, who has been replying to this thread, has blogged about it).

By on 1/20/2009 11:56 AM ()

Thank you toyvo for your response. I find your implementation very interesting. I like the idea of using reflection to instantiate the right implementation.

You guessed right, I need type classes and that is what makes most of solutions not satisfactory for me. One of the problems with the implementation you specified is that it is limited to the design site. Another is that it is not type checked. This is rather a serious problem since with this solution the operator would apply to any type as a first parameter.

I hope that type classes would be added at some point to F# cause I am often faced to situations where nothing else is of a big help unfortunately!

(one another example is when I want to treat a "Person list" and "Person" similarly as a second parameter of the operator: solution is a simple type class for which an instance is "id" for the list and [] for the "Person")

By on 1/20/2009 2:14 PM ()

Hi Sadek.

Right, of course, these 'typeclasses' do not typecheck. I'm not the one to argue that F# is a better language than Haskell, even if its .NET interop is an advantage. And so far there's no way to write an F# library that would extend the F# type sysetm.

I join the petition to add type classes to the next F#. The best we can do today on Sept 2008 F# CTP is playing with reflection.

But concerning the solution being extensible, this can be mended. Think about hacking the dispatch function to use, for example, some global state (dictionary) with instances. There may be other ways too. It's all rather ugly, but if you really want to, you can give your library users a nice interface.

By on 1/20/2009 2:35 PM ()

I agree.

Let's hope for type constructors + type classes in the next release :) It would solve my issue if it is soon before I release my library :p

Thanks again toyvo for your interesting insights. Kurt too.

By on 1/20/2009 3:42 PM ()

Hi,

I don't think that you can overload >> the way you want. You could try defining overloads on Person, or operators? Not sure at all this will work. Maybe a nice solution would be to define combinators that are functions, and stick with functions all the way (i.e. don't expose the record type to the user)

Interfaces for function types are not possible either, as a function type is a pre-existing type, and you can't implement an interface on a pre-existing type after the fact.

What you can do is make a simple wrapper type and implement an interface on that:

type MyFunc<'a,'b> = F of 'a -> 'b with interface ...

Kurt

By on 1/12/2009 7:38 AM ()

>>Interfaces for function types are not possible either, as a function type is a pre-existing type, and you can't implement an interface on a pre-existing type after the fact.

Does this mean that there is no way to abstract in F# over functions?

>>Maybe a nice solution would be to define combinators that are functions, and stick with functions all the way (i.e. don't expose the record type to the user)

Does not work for me cause i need the record type for pattern matching, and anyway the function at some point will be applied and it will be too late to add any children then.

Can I pattern match function types?

I guess what I need is a mechanism of abstraction that defines constrains that can be satisfied out of design sight and works for function types.

By on 1/12/2009 8:10 AM ()

Hi,

Hm. After that reply, I don't think I understood your question. There are plenty of means to 'abstract' over funtions - you can pass them as a value, you can partially apply them, you can use them as part of a record type, you can return a function in a member and so forth. It is not possible to pattern match functions - not sure what the behavior would be of such a thing.

The kind of overloading you want is possible with type classes, but F# does not support type classes.

From your simple example I don't really see your goal, so it's hard to provide more ideas here.

Kurt

By on 1/13/2009 11:21 AM ()

What I need is as simple as my example. I need to define the operator "<<" for both a partially applied function Child list -> Person or Person.

One way I thought of is to define an interface Nestable that will be implemented by the function type and Person type so that I can define the Operator in terms of the interface.

Another thing I thought of(which I think is rather a bad idea) is to pattern match the type, and decide how to apply in case of function.

Type Classes could help here, Interfaces over functions as well. But non of the existing F# abstraction mechanism seem to work for me. That is what I meant by saying abstracting over function Types.

By on 1/13/2009 12:31 PM ()

I guess I understood a part of the story. F# has no type constructors! I confused type synonyms for type constructors :s pity!

By on 1/17/2009 11:35 AM ()

What do you mean by type constructor? (F# has lots of type constructors, so I think we are using the same words to describe different things.) Can you give an example from another programming language, perhaps, to describe what you want to do?

By on 1/17/2009 12:19 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