New version: I made a discriminated union ("choices" or "variant" structure) "wrapNode" that has an alternative for each node type. I put a member "wrap" on each node, to return the wrapped form. I was then able to match against the wrapNode alternatives, instead of needing dynamic typing. It was also easy to collapse two levels of test "| WStmt (IfSt i)" where desired, eliminating the need to have the "isDone" flag.

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
 

#light
let ps (s:string) = s |> printfn "%s"

/// base class
type node =
  interface
    // wrap self so can match node type w/o dynamic type test.
    abstract wrap : unit -> wrapNode
  end

/// all node types wrapped into a choice.
and wrapNode =
  | WStmt of stmt
  | WExp of exp

and stmt = // Exp | IfSt
  | Exp of exp
  | IfSt of ifSt
  with interface node with
    member n.wrap() = WStmt n // wrap self

and ifSt =  // 'if' Exp 'then' Stmt ['else' Stmt]
  { Cond : exp; Then : stmt; Else : stmt option }

and exp =
  | Lit of string     // ..non-negative integer..
  | Add of exp * exp  // Exp '+' Exp
  with interface node with
    member n.wrap() = WExp n // wrap self

let func1 (n:#node) =
  match n.wrap() with
  | WStmt (IfSt i) -> ps "Handle IfSt case"
  | _ -> ps "Handle general case"

let F (n:#node) = func1 n
let L (s:string) = Exp (Lit s) 

F (L "123")
F (IfSt {Cond= Lit "true"; Then= L "12"; Else= Some (L "34")})
By on 3/27/2008 2:26 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