diff --git a/src_colibri2/core/colibri2_core.mli b/src_colibri2/core/colibri2_core.mli
index 9e3fc5993fb6bd4b3aef0703abe1df78bf3d82c6..974c065fd8aae1f400d24630e8cab171ce65d2e9 100644
--- a/src_colibri2/core/colibri2_core.mli
+++ b/src_colibri2/core/colibri2_core.mli
@@ -556,6 +556,8 @@ module Interp : sig
 
     val unfold_with :
       'a t -> init:'b -> f:('b -> 'a -> ('c, 'b) Base.Sequence.Step.t) -> 'c t
+
+    val hd_exn : 'a t -> 'a
   end
 
   type check =
diff --git a/src_colibri2/core/interp.ml b/src_colibri2/core/interp.ml
index 8559fa075398f2a0606529feb34ab66836e3d6ae..4ddca2101c30f2c41ee20f79f9971fcf1fd02674 100644
--- a/src_colibri2/core/interp.ml
+++ b/src_colibri2/core/interp.ml
@@ -123,6 +123,8 @@ module SeqLim = struct
           d.limitreached := true;
           Sequence.take (x (i + 1)) 1)
         else x (i + 1)
+
+  let hd_exn s = Sequence.hd_exn (s 1)
 end
 
 let check_of_bool = function true -> Right | false -> Wrong
@@ -486,39 +488,41 @@ module Fix_model = struct
 end
 
 let pp_gen_ground fmt = function
-  | `Ground g -> Ground.Term.pp fmt (Ground.sem g)
-  | `ClosedQuantifier g -> Ground.ClosedQuantifier.pp fmt g
-  | `NotTotallyApplied g -> Ground.NotTotallyApplied.pp fmt g
+  | `Ground g -> Fmt.pf fmt "ground term %a" Ground.Term.pp (Ground.sem g)
+  | `ClosedQuantifier g ->
+      Fmt.pf fmt "closed quantifier %a" Ground.ClosedQuantifier.pp g
+  | `NotTotallyApplied g ->
+      Fmt.pf fmt "not totally applied function %a" Ground.NotTotallyApplied.pp g
 
-let ty_gen = function
-  | `Ground g -> (Ground.sem g).ty
-  | `ClosedQuantifier _ -> Ground.Ty.bool
-  | `NotTotallyApplied _ ->
-      (* todo *)
-      assert false
+let pp_ty_gen fmt = function
+  | `Ground g -> Ground.Ty.pp fmt (Ground.sem g).ty
+  | `ClosedQuantifier _ -> Ground.Ty.pp fmt Ground.Ty.bool
+  | `NotTotallyApplied _ -> ()
 
 let () =
-  Exn_printer.register (fun fmt exn ->
+  Caml.Printexc.register_printer (fun exn ->
       match exn with
       | CantInterpretNode t ->
-          Fmt.pf fmt "Can't interpret the node %a." Node.pp t
+          Some (Fmt.str "Can't interpret the node %a." Node.pp t)
       | CantCheckGround g ->
-          Fmt.pf fmt "Can't check ground term %a of type %a." pp_gen_ground g
-            Ground.Ty.pp (ty_gen g)
+          Some
+            (Fmt.str "Can't check %a of type %a." pp_gen_ground g pp_ty_gen g)
       | CantComputeGround g ->
-          Fmt.pf fmt "Can't compute ground term %a of type %a." pp_gen_ground g
-            Ground.Ty.pp (ty_gen g)
+          Some
+            (Fmt.str "Can't compute %a of type %a." pp_gen_ground g pp_ty_gen g)
       | CantInterpretTy t ->
-          Fmt.pf fmt "Can't interpret the type %a." Ground.Ty.pp t
+          Some (Fmt.str "Can't interpret the type %a." Ground.Ty.pp t)
       | GroundTermWithoutValueAfterModelFixing g ->
-          Fmt.pf fmt "After model fixing %a of type %a has no value"
-            pp_gen_ground g Ground.Ty.pp (ty_gen g)
+          Some
+            (Fmt.str "After model fixing %a of type %a has no value"
+               pp_gen_ground g pp_ty_gen g)
       | ArgOfGroundTermWithoutValueAfterModelFixing (g, n) ->
-          Fmt.pf fmt
-            "After model fixing arguments %a of %a of type %a has no value"
-            Node.pp n Ground.Term.pp (Ground.sem g) Ground.Ty.pp
-            (Ground.sem g).ty
-      | exn -> raise exn)
+          Some
+            (Fmt.str
+               "After model fixing arguments %a of %a of type %a has no value"
+               Node.pp n Ground.Term.pp (Ground.sem g) Ground.Ty.pp
+               (Ground.sem g).ty)
+      | _ -> None)
 
 (** Helpers *)
 module WatchArgs = struct
diff --git a/src_colibri2/core/interp.mli b/src_colibri2/core/interp.mli
index 9d55c9d15838d3ebf6ab4de7328dff963c3e3ca3..01211721e12551a00104946115e437a0cd540799 100644
--- a/src_colibri2/core/interp.mli
+++ b/src_colibri2/core/interp.mli
@@ -42,6 +42,8 @@ module SeqLim : sig
 
   val unfold_with :
     'a t -> init:'b -> f:('b -> 'a -> ('c, 'b) Sequence.Step.t) -> 'c t
+
+  val hd_exn : 'a t -> 'a
 end
 
 type check = Right | Wrong | NA | Unknown
diff --git a/src_colibri2/popop_lib/exn_printer.ml b/src_colibri2/popop_lib/exn_printer.ml
index 7efec44d2aa2b468fdfae3d6fef937f15467e49a..291ba0bf2fbfb19d50ad2f09d6cca9c58cdf4564 100644
--- a/src_colibri2/popop_lib/exn_printer.ml
+++ b/src_colibri2/popop_lib/exn_printer.ml
@@ -33,9 +33,6 @@ let exn_printer fmt exn =
   with Exit_loop -> ()
 
 
-let () =
-  Printexc.register_printer (fun exn -> Some (Pp.string_of exn_printer exn))
-
 
 (** usual version *)
 let exn_printer fmt exn =
diff --git a/src_colibri2/solver/input.ml b/src_colibri2/solver/input.ml
index 89e160d477e264a4b61fee38f0f2d3f60117f413..d9e85ca2a9d59ea32b25f99e8f89d81cf7a8d347 100644
--- a/src_colibri2/solver/input.ml
+++ b/src_colibri2/solver/input.ml
@@ -85,7 +85,7 @@ let split_input = function
   | `Stdin -> (Sys.getcwd (), `Stdin)
   | `File f -> (Filename.dirname f, `File (Filename.basename f))
 
-let print_exn st = function
+let print_exn_and_exit st = function
   (* Sigint, potentially wrapped by the typechecker *)
   | Pipeline.Sigint
   | Dolmen_loop.Typer.T.Typing_error
@@ -175,14 +175,14 @@ let print_exn st = function
          command line"
   (* Generic catch-all *)
   | e ->
-      State.error st "@[<hv>Unhandled exception:@ %s@]" (Printexc.to_string e)
+      State.error ~code:Dolmen_loop.Code.bug st "@[<hv>Internal error:@ %s@]"
+        (Printexc.to_string e)
 
 let handle_exn_with_exit st bt exn =
   if st.State.debug then (
     Printexc.print_raw_backtrace stderr bt;
     Format.eprintf "%s@." (Printexc.to_string exn));
-  let () = print_exn st exn in
-  exit 2
+  print_exn_and_exit st exn
 
 let handle_exn_with_error _ bt exn = Printexc.raise_with_backtrace exn bt
 
diff --git a/src_colibri2/tests/solve/models/dune.inc b/src_colibri2/tests/solve/models/dune.inc
index 0e2e72b0121a760a25b46721ab67f33c4a0435c9..d381eb29b1999f7ed376e200b80b3818eab53088 100644
--- a/src_colibri2/tests/solve/models/dune.inc
+++ b/src_colibri2/tests/solve/models/dune.inc
@@ -1,4 +1,6 @@
 (rule (action (with-stdout-to abs_real.smt2.res (run %{bin:colibri2} --size=100M --time=30s --max-steps 3500 --check-status colibri2 %{dep:abs_real.smt2}))))
 (rule (alias runtest) (action (diff abs_real.smt2.oracle abs_real.smt2.res)))
+(rule (action (with-stdout-to function.smt2.res (run %{bin:colibri2} --size=100M --time=30s --max-steps 3500 --check-status colibri2 %{dep:function.smt2}))))
+(rule (alias runtest) (action (diff function.smt2.oracle function.smt2.res)))
 (rule (action (with-stdout-to get_value.smt2.res (run %{bin:colibri2} --size=100M --time=30s --max-steps 3500 --check-status colibri2 %{dep:get_value.smt2}))))
 (rule (alias runtest) (action (diff get_value.smt2.oracle get_value.smt2.res)))
diff --git a/src_colibri2/theories/quantifier/uninterp.ml b/src_colibri2/theories/quantifier/uninterp.ml
index 393b91ecf69bc0311554a432960094792120a9a1..2e6b6b9a88d7287d0bca1ba178081ba58b35352e 100644
--- a/src_colibri2/theories/quantifier/uninterp.ml
+++ b/src_colibri2/theories/quantifier/uninterp.ml
@@ -283,16 +283,28 @@ module UFModel = struct
 
   module Hargs = Context.Hashtbl (Values)
 
+  type t = { known : Value.t Hargs.t; other : Value.t option Context.Ref.t }
+
   let env =
-    HConst.create Fmt.nop "Uninterp.UFModel.env" (fun c _ -> Hargs.create c)
+    HConst.create Fmt.nop "Uninterp.UFModel.env" (fun c _ ->
+        { known = Hargs.create c; other = Context.Ref.create c None })
 
   let find d (g : Ground.s) lv =
     let h = HConst.find env d { tc = g.app; ta = g.tyargs } in
-    Hargs.find_opt h lv
+    Hargs.find_opt h.known lv
 
   let set d (g : Ground.s) lv v =
     let h = HConst.find env d { tc = g.app; ta = g.tyargs } in
-    Hargs.set h lv v
+    Hargs.set h.known lv v
+
+  let get_other d (g : Ground.s) =
+    let h = HConst.find env d { tc = g.app; ta = g.tyargs } in
+    match Context.Ref.get h.other with
+    | None ->
+        let o = Interp.SeqLim.hd_exn (Interp.ty d g.ty) in
+        Context.Ref.set h.other (Some o);
+        o
+    | Some x -> x
 
   let on_uninterpreted_domain d g =
     let check_or_update g d _ _ =
@@ -318,6 +330,20 @@ module UFModel = struct
     Interp.WatchArgs.create d on_uninterpreted_domain g
 end
 
+module V' = struct
+  module T = struct
+    type t = { maps : Value.t UFModel.Values.M.t; other : Value.t }
+    [@@deriving ord, eq, hash, show]
+  end
+
+  include T
+  include Colibri2_popop_lib.Popop_stdlib.MkDatatype (T)
+
+  let name = "fun"
+end
+
+module V = Value.Register (V')
+
 module On_uninterpreted_domain = struct
   (** For model fixing *)
 
@@ -336,9 +362,7 @@ module On_uninterpreted_domain = struct
     let lv = IArray.map ~f:interp s.args in
     match UFModel.find d s lv with
     | Some v' -> Value v'
-    | None ->
-        (* todo error because should be computed? *)
-        NA
+    | None -> Value (UFModel.get_other d s)
 end
 
 let init_check d =
@@ -358,6 +382,12 @@ let converter d (t : Ground.t) =
 let th_register env =
   Ground.register_converter env converter;
   init_check env;
-  init_ty env
+  init_ty env;
+  Interp.Register.compute env (fun d t ->
+      match Ground.sem t with
+      | { app = { builtin = Expr.Base; _ }; args; _ }
+        when IArray.length args >= 1 ->
+          On_uninterpreted_domain.compute d t
+      | _ -> NA)
 
 let () = Init.add_default_theory th_register