let rec print_value v = match v.value with
    | Unit     -> "()"
    | Bool i   -> string_of_bool i
    | Int i    -> string_of_int i
    | Float f  -> string_of_float f
    | String s -> Printf.sprintf "%S" s
    | Source s -> "<source>"
    | Request s -> "<request>"
    | Encoder e -> Encoder.string_of_format e
    | List l ->
        "["^(String.concat ", " (List.map print_value l))^"]"
    | Ref a ->
        Printf.sprintf "ref(%s)" (print_value !a)
    | Product (a,b) ->
        Printf.sprintf "(%s,%s)" (print_value a) (print_value b)
    | Fun ([],_,_,x) when is_ground x -> "{"^print_term x^"}"
    | Fun (l,_,_,x) when is_ground x -> 
        let f (label,_,value) =
          match label, value with
            | "",    None -> "_"
            | "",    Some v -> Printf.sprintf "_=%s" (print_value v)
            | label, Some v -> 
                Printf.sprintf "~%s=%s" label (print_value v)
            | label, None ->
                Printf.sprintf "~%s" label
        in
        let args = List.map f l in
        Printf.sprintf "fun (%s) -> %s" (String.concat "," args) (print_term x)
    | Fun _ | FFI _ -> "<fun>"