let rec dist x = simplify_dist (
match x with
| Var v -> [(x, 1.)]
| Lam (a, b) ->
map (fun (b1,p) -> (Lam (a, b1)), p) (dist b)
| App (a, b) -> (dist_apply a b)
| Flip (p, a, b) ->
append (weight_dist p (dist a)) (weight_dist (1. -. p) (dist b))
| Const _ -> [(x, 1.)]
| Case _ -> [(x, 1.)])
and dist_apply a b =
match a with
| Lam (x, s) ->
if contains_var x s
then
let app (b, bProb) =
weight_dist bProb (dist (subst x b s))
in concat (map app (dist b))
else
dist s
| Case branches ->
let dist_branch (b, bProb) =
match b with
| Const n ->
weight_dist bProb (dist (assoc n branches))
| Var _ -> raise (Prob_error "case: got a var")
| _ -> raise (Prob_error "error in case") in
concat (map dist_branch (dist b))
| _ -> [(App (a, b), 1.)]