Hi,

There are a few problems.

First, declare family with:

1
let family = [ec; tb]

List items are separed by ";" and not "," (commas are for tuples).

If you want to iterate and print data, use List.iter instead of
fold_left. List.iter first argument is a 'a -> unit (meaning, a
function that doesn't return a value). List.fold_left is a bit more
complex: look in the manual
([link:research.microsoft.com]

Finally, you should add "box" function. This way, your "what" function
accepts anything ('a), instead of obj.

1
2
let what o =
    match box o with

Laurent

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

By the way this is the .NET way to face the problem, and you are resorting to runtime type checking for pattern matching. A more F# way to do the same is to use union types:

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
#light

type Person = {
  first : string
  last : string
  age : int
}

type Pet = {
  name : string
  species : string
}

let tb = { first = "T"; last = "Breezy"; age = 34 }
let ec = { first="French"; last="Fry"; age = 29}
let ak9cb = { name="ally"; species="cocker"}

type PersonPet =
| PetP of Pet
| PersonP of Person

let family = [ PetP ak9cb; PersonP tb; PersonP ec ]

let what p =
  match p with
  | PersonP p -> "people is people"
  | PetP p -> "pets are people too!"

List.iter  (fun x -> printf "%s" (what(x))) family

Antonio

By on 12/13/2007 1:44 PM ()

I knew I was a fool, and should have seen the semi colons. I just told a coworker two days ago that the semicolons would be a spur in my behind - hopefully this is enough of a lesson to get my eyes into gear. What makes one option more of a ".NET" way versus a F# way? why in the .NET way does everything have to be cast as obj? I had tried with a union before and recieved a differnt set of issues (my match wasn't coded correctly), so I decided that wasnt the way to go. Anyhow THANK YOU - both solutions worked charmingly, and I do like the F# technique better as I can better control what goes into my list.

My final solution combined both techniques into a single "what" function that uses inner functions to provide the proper implmentation. Any critique would be appreciated; i really appreciate the help.

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
#light
type Person = {
    first: string
    last: string 
    age: int
} 

type Pet = {
    name: string
    species: string
}

 

type PersonPet =
    | PetP of Pet
    | PersonP of Person

let what o =
    let inner_obj (o:obj) = 
        match box o with
        | :? Person as p -> p.first ^ " " ^ p.last ^ " is a Person"
        | :? Pet as pp -> pp.name ^ " is a Pet"
        | _ -> failwith "can't find my cheese" in

    let inner_union o = 
        match o with
        | PersonP p -> "people is people"
        | PetP p -> "pets are people too!" in

    match box o with
    | :? PersonPet as p -> inner_union(p)
    | obj as o -> inner_obj(box o)
    
let printEm aList =
    List.iter (fun item -> print_string(what(item) ^ "\n")) aList
    print_string("\n\n") 


let tb = {first="T"; last="Breezy"; age=34}
let ec = {first="French"; last="Fry"; age=29}
let ak9cb = {name="ally"; species="cocker"}

let family = [(ec :> obj); (ak9cb :> obj); (tb :> obj)]

printEm(family)

let anotherFamily = [PersonP tb; PersonP ec; PetP ak9cb]

printEm(anotherFamily)
By on 12/14/2007 7:25 AM ()

I think the solution with unions is better, because it's statically typed. The compiler can check everything. With unions, your "what" function cannot fail at runtime.

When you use boxing to an obj type, you get dynamic typing. This means the compilater cannot check types: it's only an "obj". Your function will fail at run-time if there's a type error (look: you had to add a failwith).

When possible, I suggest you to avoid conversions to obj (or box functions), as your code gets less safe.

Laurent.

By on 12/14/2007 3:21 PM ()

I assume you were interested in applying the function to each item in the list. First of all the list uses ; to separate items, commas lead to tuples. You can better experiment using F# interactive that helps you finding problem while typing.

A working version of the first program is:

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
#light

type Person = {
  first : string
  last : string
  age : int
}

type Pet = {
  name : string
  species : string
}

let tb = { first = "T"; last = "Breezy"; age = 34 }
let ec = { first="French"; last="Fry"; age = 29}
let ak9cb = { name="ally"; species="cocker"}

let what (o:obj) =
  match o with
  | :? Person as p -> "people is people"
  | :? Pet as pp -> "pets are people too!"
  | _ -> failwith "can't find my cheese"

let family = [ (ec :> obj); (tb :> obj); (ak9cb :> obj) ]
List.iter (fun item -> printf "%s" (what(item))) family

Note that I upcasted all the references to obj to have an homogeneous list of objects. I used iter rather than fold since I expect you were interested in applying the function to each item.

Antonio

By on 12/13/2007 1:25 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