[Agda] how does BUILTIN work - practical programming in Agda

Nils Anders Danielsson nad at chalmers.se
Mon Dec 5 19:02:02 CET 2011


On 2011-12-05 18:06, Alan Jeffrey wrote:
> I'm not sure coinduction is the way to give laziness hints to the
> compiler, as that might impact the semantics of the terms (e.g. lazy
> lists would become co-lists even if the laziness was only intended to
> be for efficiency reasons, not for coinduction).

It is easy to imagine using a dedicated type constructor for laziness
(as is often done in strict languages):

   data Thunk (A : Set) : Set where  -- /Not/ a record type.
     thunk : (x : A) → Thunk A

   {-# BUILTIN LAZY thunk #-}

   force : {A : Set} → Thunk A → A
   force (thunk x) = x

   seq : {A B : Set} → Thunk A → B → B
   seq (thunk _) x = x

   if_then_else_ : {A : Set} → Bool → Thunk A → Thunk A → A
   if true  then x else y = force x
   if false then x else y = force y

Note that with this approach the type-checker is free to reduce seqs,
because the reduction removes the thunk. Occurrences of seq may be
present in types, but we can prove the following lemma:

   seq-vanishes : {A B : Set} (x : Thunk A) (y : B) → seq x y ≡ y
   seq-vanishes (thunk _) _ = refl

Something like this would be /very/ easy to implement, at least in the
MAlonzo backend.

I wonder how awkward it is to program with explicit laziness. My
experience is that the explicit distinction between inductive and
coinductive types make it easier for me to understand the programs I'm
writing.

Aside: I once designed a library for keeping track of amortised time
complexity of non-strict programs. This library used a Thunk monad
annotated with an upper bound on the number of steps needed to compute
the thunk to weak head normal form (more or less; see the paper for
details):

   Lightweight Semiformal Time Complexity Analysis for Purely Functional
     Data Structures
   http://www.cse.chalmers.se/~nad/publications/danielsson-popl2008.html

-- 
/NAD



More information about the Agda mailing list