Skip to content

Instantly share code, notes, and snippets.

@t0yv0
Created July 23, 2010 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t0yv0/487618 to your computer and use it in GitHub Desktop.
Save t0yv0/487618 to your computer and use it in GitHub Desktop.
type View<'T1,'T2> =
{
Get : 'T1 -> option<'T2>
Set : 'T2 -> 'T1 -> 'T1
}
static member Find() =
let t1 = typeof<'T1>
let t2 = typeof<'T2>
if R.IsRecord t1 then
let reader = R.RecordReader(t1).Value
let ctor = R.RecordConstructor(t1).Value
let get i x =
Some (reader(x).[i] :?> 'T2)
let set i (v: 'T2) (x: 'T1) =
let a = reader x
a.[i] <- box v
ctor a :?> 'T1
R.RecordFields(t1).Value
|> Seq.mapi (fun i p ->
if p.PropertyType = t2 then
Some {
Get = get i
Set = set i
}
else
None)
|> Seq.choose id
|> Seq.toList
elif R.IsUnion t1 then
let tagReader = R.UnionTagReader(t1).Value
let cases = R.UnionCases(t1).Value
let readers = [| for c in cases -> R.UnionReader c |]
let ctors = [| for c in cases -> R.UnionConstructor c |]
let get i j (x: 'T1) : option<'T2> =
let tag = tagReader x
if tag = i then
let r = readers.[i]
Some (r(x).[j] :?> 'T2)
else
None
let set i j (v: 'T2) (x: 'T1) : 'T1 =
let tag = tagReader x
if tag = i then
let r = readers.[i]
let c = ctors.[i]
let a = r x
a.[j] <- box v
c a :?> 'T1
else
x
cases
|> Seq.mapi (fun i case ->
case.GetFields()
|> Seq.mapi (fun j field ->
if field.PropertyType = t2 then
Some {
Get = get i j
Set = set i j
}
else
None))
|> Seq.concat
|> Seq.choose id
|> Seq.toList
else
[]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment