An example of replacing compilation times that degrade a program

Imagine a naive compiler of typed lambda calculus (to eliminate the rather painful problem of nontermination and implicit recursion) that uses normalization (including substitutions for lambdas) as "optimization".

For simple programs, when most or all of the variables are used only once, normalization reduces and speeds up programs.

It is "obvious" to me that in general this is not a good idea. That is, since normalization reduces sharing, there are conditions that get worse due to optimization. Term with 2 multiplications

\x -> let a = x * x in a * a

gets "optimized" in

\x -> (x * x) * (x * x)

with 3 of them.

How to build an example that is getting worse? Is there a term that is likely to overflow RAM during normalization?

We work in a strongly normalized type system, so a discrepancy is impossible, for example. in a suitable subset of the system F with constants and delta rules.

Or with a “free” approach to adding type constants mul, for example.

\mul x -> let a = mul x x in mul a a

Therefore, instead of adding constants, they are simply "additional parameters provided at runtime."

The question may seem to belong to SE Computer Science, but IMO is really the first level, so I find it more appropriate here.

+4
source share
1 answer

, :

let p:nat->nat->nat - ( ).

q:(nat->nat->nat)->nat->nat->nat = \f:(nat->nat->nat).(\a b:nat.f (f a b) (f a b))

q p => \a b.p (p a b) (p a b)

q (q p) => \c d.q p (q p c d) (q p c d) 
  => \c d.q p (p (p c d) (p c d)) (p (p c d) (p c d))
  => \c d.p (p [p (p (p c d) (p c d))] [p (p (p c d) (p c d))]) (p [p (p (p c d) (p c d))] [p (p (p c d) (p c d))])

q (q (q p))

. Coq:

Section Expand.

Variable nat:Type.

Variable p:nat->nat->nat.

Definition q:(nat->nat->nat)->nat->nat->nat :=
  fun f:(nat->nat->nat) => fun a b:nat => f (f a b) (f a b).

Eval compute in (q p).
(*
  = fun a b : nat => p (p a b) (p a b)
     : nat -> nat -> nat
*)

Eval compute in (q (q p)).
(*
  = fun a b : nat =>
       p (p (p (p a b) (p a b)) (p (p a b) (p a b)))
         (p (p (p a b) (p a b)) (p (p a b) (p a b)))
     : nat -> nat -> nat
*)

Eval compute in (q (q (q p))).
(*
     = fun a b : nat =>
       p
         (p
            (p
               (p
                  (p (p (p (p a b) (p a b)) (p (p a b) (p a b)))
                     (p (p (p a b) (p a b)) (p (p a b) (p a b))))
                  (p (p (p (p a b) (p a b)) (p (p a b) (p a b)))
                 =============SKIPPED LOTS OF LINES==========
                  (p (p (p (p a b) (p a b)) (p (p a b) (p a b)))
                     (p (p (p a b) (p a b)) (p (p a b) (p a b)))))))
     : nat -> nat -> nat
*)

- ( ):

Prelude> q f a b = f (f a b) (f a b)
Prelude> (q $ q $ q (+)) 1 1
256
Prelude> (q $ q $ q $ q (+)) 1 1
65536
Prelude> (q $ q $ q $ q $ q (+)) 1 1
4294967296
Prelude> (q $ q $ q $ q $ q $ q (+)) 1 1
18446744073709551616
Prelude> (q $q $ q $ q $ q $ q $ q (+)) 1 1
340282366920938463463374607431768211456
Prelude> (q $ q $ q $ q $ q $ q $ q $ q (+)) 1 1
115792089237316195423570985008687907853269984665640564039457584007913129639936
Prelude> (q $ q $ q $ q $ q $ q $ q $ q $ q (+)) 1 1
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
+2

Source: https://habr.com/ru/post/1663899/


All Articles