module Main %default total -- An expensive function. qib : Nat -> Nat qib Z = 1 qib (S Z) = 2 qib (S (S n)) = qib n * qib (S n) -- An equality whose size reflects the size of numbers. data Equals : Nat -> Nat -> Type where EqZ : Z `Equals` Z EqS : m `Equals` n -> S m `Equals` S n eq_refl : {n : Nat} -> n `Equals` n eq_refl {n = Z} = EqZ eq_refl {n = S n} = EqS eq_refl -- Here, the proof is very expensive to compute. -- We add a recursive argument to prevent Idris from inlining the function. f : (r, n : Nat) -> Subset Nat (\k => qib n `Equals` qib k) f Z n = Element n eq_refl f (S r) n = f r n -- A (contrived) relation, just to have something to show. data Represents : Nat -> Nat -> Type where Axiom : (n : Nat) -> qib n `Represents` n -- Here, the witness is very expensive to compute. -- We add a recursive argument to prevent Idris from inlining the function. g : (r, n : Nat) -> Exists (\k : Nat => k `Represents` n) g Z n = Evidence (qib n) (Axiom n) g (S r) n = g r n fmt : qib n `Represents` n -> String fmt (Axiom n) = "Axiom " ++ show n main : IO () main = do n <- map (const (the Nat 10000)) (putStrLn "*oink*") putStrLn . show $ getWitness (f 4 n) putStrLn . fmt $ getProof (g 4 n)