Repository: idris-lang/Idris-dev

Issue #172: fromList and exponential compile time
Created: 2013-01-30T14:49:02Z
The following program
> module Main

> n : Nat
> n = 100

> nats : Vect Nat n
> nats = fromList [1..n]

> main : IO ()
> main = putStrLn (show (cast n))

executes in constant time in n as one would expect. Compilation, however, takes exponential time:
   n      user time
 100      0m0.728s
 200      0m1.304s 
 400      0m3.352s
 800      0m14.737s
1600      1m30.258s

In fact, at n = 3200, compilation virtually stalls (on my laptop) after having eaten up the whole memory (8GB). Notice that replacing
> nats : Vect Nat n
> nats = fromList [1..n]

with
> nats : List Nat
> nats = [1..n]

yields constant compile times. Is it possible to construct vectors of natural numbers of length n in at most linear time (in n) ?

Duplicate issue #2837: Let clauses make execution about 300 times slower
Created: 2015-12-01T19:57:55Z
The program
> module Main

> import NatGCD
> import NatGCDOperations
> import NatGCDProperties
> import NatGCDAlgorithm
> import NatDivisor
> import NatDivisorOperations
> import NatDivisorProperties
> import PNat
> import PNatOperations
> import PNatProperties
> import NatPositive

> %default total

> m  : Nat
> m  = 2067
> %freeze m

> x  : (Nat, PNat)
> x  = (Main.m, fromNat 616 (LTESucc LTEZero))

> d'     : PNat
> d'     = snd Main.x
> d      : Nat
> d      = toNat Main.d'
> g      : Nat
> g      = gcdAlg Main.m Main.d
> prf    : (GCD Main.g Main.m Main.d)
> prf    = gcdAlgLemma Main.m Main.d
> gDm    : (Main.g `Divisor` Main.m)
> gDm    = gcdDivisorFst Main.prf
> gDd    : (Main.g `Divisor` Main.d)
> gDd    = gcdDivisorSnd Main.prf
> qmg    : Nat
> qmg    = quotient Main.m Main.g Main.gDm
> qdg    : Nat
> qdg    = quotient Main.d Main.g Main.gDd
> zLTd   : (Z `LT` Main.d)
> zLTd   = toNatLTLemma Main.d'
> zLTqdg : (Z `LT` Main.qdg)
> zLTqdg = quotientPreservesPositivity Main.d Main.g Main.gDd Main.zLTd
> y      : (Nat, PNat)
> y      = (Main.qmg, fromNat Main.qdg Main.zLTqdg)

> main : IO ()               
> main = do putStrLn (show y)

executes in about 0.5 seconds. But it takes about 150 seconds for
> module Main

> import NatGCD
> import NatGCDOperations
> import NatGCDProperties
> import NatGCDAlgorithm
> import NatDivisor
> import NatDivisorOperations
> import NatDivisorProperties
> import PNat
> import PNatOperations
> import PNatProperties
> import NatPositive

> %default total

> m  : Nat
> m  = 2067
> %freeze m

> x  : (Nat, PNat)
> x  = (Main.m, fromNat 616 (LTESucc LTEZero))

> y  : (Nat, PNat)
> y  = let m      : Nat
>                 = fst Main.x in 
>      let d'     : PNat
>                 = snd Main.x in 
>      let d      : Nat
>                 = toNat d' in 
>      let g      : Nat
>                 = gcdAlg m d in
>      let prf    : (GCD g m d)
>                 = gcdAlgLemma m d in
>      let gDm    : (g `Divisor` m)
>                 = gcdDivisorFst prf in
>      let gDd    : (g `Divisor` d)
>                 = gcdDivisorSnd prf in
>      let qmg    : Nat
>                 = quotient m g gDm in
>      let qdg    : Nat
>                 = quotient d g gDd in
>      let zLTd   : (Z `LT` d)
>                 = toNatLTLemma d' in 
>      let zLTqdg : (Z `LT` qdg)
>                 = quotientPreservesPositivity d g gDd zLTd in
>      (qmg, fromNat qdg zLTqdg)

> main : IO ()               
> main = do putStrLn (show y)

to execute. Similarly,
> module Main

> import Fraction
> import FractionOperations
> import FractionProperties
> import PNat
> import PNatOperations
> import PNatProperties

> %default total

> x : Fraction
> x = (2067, fromNat 616 (LTESucc LTEZero)) 
> %freeze x

> y : Fraction
> y = normalize x

> main : IO ()               
> main = do putStrLn (show y)

runs in about 150 seconds. Here, normalize is implemented in terms of let expressions as in the second example. Thus, it appears that the execution speed worsens by a factor of about 300 if the same computation is expressed in terms of let clauses. The three programs can be downloaded from
https://github.com/nicolabotta/SeqDecProbs/tree/master/frameworks/14-
as NatGCDAlgorithmTest.1.lidr, NatGCDAlgorithmTest.2.lidr and FractionTest.lidr, respectively. The function normalize is implemented in FractionOperations.lidr. What is going on here?

Closing comment (2016-06-03T17:35:38Z): I think this is related to #172  and #3199, so I will close it as a duplicate if it is OK.