# Implementing TrueSkill with Fun

• ### Question

• Hello,

I'm trying to implement TrueSkill using Fun. The meaning of type (player[] * outcome)[] is: array of pairs (team, outcome for the team), and team is the array of players. Here is my model:

```[<ReflectedDefinition>]
let skillsPrior (g: player) (skills: float[]) =
random (GaussianFromMeanAndPrecision(skills.[g], 1.0 / beta2))
[<ReflectedDefinition>]
let performance s =
random (GaussianFromMeanAndPrecision(s, 1.0 / sigma2))
[<ReflectedDefinition>]
let teamPerf (t: float[]) =
(Array.sum t) / (float (Array.length t))
[<ReflectedDefinition>]
let perfDiff (perfs: (float * outcome)[]) =
let pairs = Array.zip perfs.[..(Array.length perfs - 1)] perfs.[1..]
[|for ((fst, outcome1), (snd, outcome2)) in pairs -> (snd - fst, outcome2 - outcome1)|]
[<ReflectedDefinition>]
let posterior (difs: (float * outcome)[]) =
for (diff, o) in Array.toList difs do
if o > 0 then
observe (diff > drawMargin)
elif o < 0 then
observe (diff < -drawMargin)
else
observe ((diff >= -drawMargin) && (diff <= drawMargin))
[<ReflectedDefinition>]
let trueSkill (game: (player[] * outcome)[]) (skills: float[]) =
let (teams, outcomes) = Array.unzip game
let priors = [|for team in teams ->
[|for pl in team -> skillsPrior pl skills|]|]
let pr = Array.zip priors outcomes

let perfs = [|for team in priors ->
[|for pl in team -> performance pl|]|]
let teamPerfs = [|for team in perfs -> teamPerf team|]
let perfDiffs = perfDiff (Array.zip teamPerfs outcomes)
(posterior perfDiffs, priors)

let model = makeModel <@ trueSkill @>```

It compiles correctly, but rises following exception:

```Unhandled Exception:
System.Exception: couldn't unquote: NewUnionCase (None)
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[e,FSharpExpr] (Microsoft.FSharp.Collections.FSharpList`1 cons, Microsoft.FSharp.Core.FSharpFunc`2 f, Microsoft.FSharp.Collections.FSharpList`1 x) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Primitives.Basics.List.map[FSharpExpr,e] (Microsoft.FSharp.Core.FSharpFunc`2 mapping, Microsoft.FSharp.Collections.FSharpList`1 x) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Collections.ListModule.Map[FSharpExpr,e] (Microsoft.FSharp.Core.FSharpFunc`2 mapping, Microsoft.FSharp.Collections.FSharpList`1 list) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquoteBody (Microsoft.FSharp.Quotations.FSharpExpr e) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.addFunDef (Microsoft.FSharp.Collections.FSharpMap`2 ctx, System.Reflection.MethodInfo m, Microsoft.FSharp.Quotations.FSharpExpr e) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference+compile_type@62-1.Invoke (Microsoft.FSharp.Collections.FSharpMap`2 ctx, System.Tuple`2 tupledArg) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpMap`2[System.String,MicrosoftResearch.Infer.Fun.Core.Syntax+Body],System.Tuple`2[System.Reflection.MethodInfo,Microsoft.FSharp.Quotations.FSharpExpr]].InvokeFast[FSharpMap`2] (Microsoft.FSharp.Core.FSharpFunc`2 func, Microsoft.FSharp.Collections.FSharpMap`2 arg1, System.Tuple`2 arg2) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Collections.SeqModule.Fold[Tuple`2,FSharpMap`2] (Microsoft.FSharp.Core.FSharpFunc`2 folder, Microsoft.FSharp.Collections.FSharpMap`2 state, IEnumerable`1 source) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.compile_type@60 (Microsoft.FSharp.Core.FSharpRef`1 procs, System.Type t) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.compile_assembly@64 (Microsoft.FSharp.Core.FSharpRef`1 procs, System.Reflection.Assembly a) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.getAssemblyContext () [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.makeModel[Tuple`2[],FSharpFunc`2] (Microsoft.FSharp.Quotations.FSharpExpr`1 f) [0x00000] in <filename unknown>:0
at <StartupCode\$Trueskill>.\$TrueSkill2.main@ () [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Exception: couldn't unquote: NewUnionCase (None)
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[e,FSharpExpr] (Microsoft.FSharp.Collections.FSharpList`1 cons, Microsoft.FSharp.Core.FSharpFunc`2 f, Microsoft.FSharp.Collections.FSharpList`1 x) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Primitives.Basics.List.map[FSharpExpr,e] (Microsoft.FSharp.Core.FSharpFunc`2 mapping, Microsoft.FSharp.Collections.FSharpList`1 x) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Collections.ListModule.Map[FSharpExpr,e] (Microsoft.FSharp.Core.FSharpFunc`2 mapping, Microsoft.FSharp.Collections.FSharpList`1 list) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquote (Microsoft.FSharp.Quotations.FSharpExpr _arg1) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Syntax+Reflection.unquoteBody (Microsoft.FSharp.Quotations.FSharpExpr e) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.addFunDef (Microsoft.FSharp.Collections.FSharpMap`2 ctx, System.Reflection.MethodInfo m, Microsoft.FSharp.Quotations.FSharpExpr e) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference+compile_type@62-1.Invoke (Microsoft.FSharp.Collections.FSharpMap`2 ctx, System.Tuple`2 tupledArg) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Collections.FSharpMap`2[System.String,MicrosoftResearch.Infer.Fun.Core.Syntax+Body],System.Tuple`2[System.Reflection.MethodInfo,Microsoft.FSharp.Quotations.FSharpExpr]].InvokeFast[FSharpMap`2] (Microsoft.FSharp.Core.FSharpFunc`2 func, Microsoft.FSharp.Collections.FSharpMap`2 arg1, System.Tuple`2 arg2) [0x00000] in <filename unknown>:0
at Microsoft.FSharp.Collections.SeqModule.Fold[Tuple`2,FSharpMap`2] (Microsoft.FSharp.Core.FSharpFunc`2 folder, Microsoft.FSharp.Collections.FSharpMap`2 state, IEnumerable`1 source) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.compile_type@60 (Microsoft.FSharp.Core.FSharpRef`1 procs, System.Type t) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.compile_assembly@64 (Microsoft.FSharp.Core.FSharpRef`1 procs, System.Reflection.Assembly a) [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.getAssemblyContext () [0x00000] in <filename unknown>:0
at MicrosoftResearch.Infer.Fun.FSharp.Inference.makeModel[Tuple`2[],FSharpFunc`2] (Microsoft.FSharp.Quotations.FSharpExpr`1 f) [0x00000] in <filename unknown>:0
at <StartupCode\$Trueskill>.\$TrueSkill2.main@ () [0x00000] in <filename unknown>:0 ```

I'd be very grateful is you point me where I'm wrong.

Thank you,

Dmitry.

Tuesday, May 14, 2013 10:38 AM

### All replies

• Hi Dmitry,

Part of the problem is that you are stepping outside the supported subset of F# that Fun actually supports, for example using array slices, Array.sum, Array.unzip and a curried model. However, even with rewriting to avoid those issues, I've been unable to produce a version of this that compiles due to other issues. I'm currently traveling but will investigate some more when I find time or return to work next week.

Thanks,

Claudio

Thursday, May 16, 2013 2:11 PM
• Hi Claudio,

Where can I find a list of supported F# functions?

Thank you,

Dmitry.

Saturday, May 18, 2013 11:49 AM
• Hi Dmitry,

For the record, the syntax of Fun is described in the User Guide (Section: The Grammar and Semantics of Fun)

Any external functions that you call must have Infer.NET factors registered for them, see the AddFun sample for how this can be done. Also, there are severe restrictions on the expressions you can use to index into arrays.

Unfortunately, I'm still stumped trying to get your code past Fun and haven't figured out a way to replace the use of array slicing.

Thanks,

Claudio

Tuesday, May 21, 2013 3:37 PM