[clean-list] Passing an environment around

=?iso-8859-1?Q?Jos=E9_Romildo_Malaquias?= romildo@urano.iceb.ufop.br
Thu, 19 Oct 2000 09:16:03 -0200


On Thu, Oct 19, 2000 at 10:42:05AM +0200, Pieter Koopman wrote:
> Hello Romildo and clean-list
> 
> At 05:12 18/10/00 -0200, José Romildo Malaquias wrote:
> >Hello.
> >
> >I am implementing a Computer Algebra system (CALG) in Clean, and I have a
> >problem I would like the opinion of Clean programmers.
> 
> ...[snip]...
> 
> You can use the curried functions to implement infix operator to implement 
> infix operators with 3 (or more) arguments.
>
> [ ... skip the function composition operator example ...]
> 
> A more elaborated example is a very simple evaluator for expressions 
> constisting of values and names:
> 
> ------------------
> module calg
> 
> import StdEnv
> 
> :: Memory :== [(Name,Value)]
> 
> read :: Name Memory -> Value
> read name [] = abort ("No value for "+++toString name)
> read name [(n,v):r]
>          | n==name
>                  = v
>                  = read name r
> 
> :: Operator :== Memory -> Value
> 
> //name :: Name -> Operator
> name :== read
> 
> value :: Value -> Operator
> value c = \mem -> c
> 
> (.+.) infixl 6 :: !Operator !Operator -> Operator
> (.+.) e1 e2 = \mem -> e1 mem + e2 mem
> 
> (.*.) infixl 7 :: !Operator !Operator -> Operator
> (.*.) e1 e2 = \mem ->  e1 mem * e2 mem
> 
> :: Name :== String
> :: Value        :== Int
> 
> f :: Operator Operator -> Operator
> f x y = x .+. y .+. y
> 
> Start = (value 2 .*. f (value 7) (value 1 .+. name "y" .*. name "z")) amemory
> where
>          amemory = [("x",1),("y",2),("z",3)]
> ---------------------
> 
> If you want to prevent the double evaluation of the second argument of the 
> function f you can replace the function by:
> 
> fopt :: Operator Operator -> Operator
> fopt x y = \mem -> let vx = x mem; vy = y mem in vx + vy + vy
> 
> Does this help?

Your sugestion is the first alternative to solve the problem
I have posted in the original message of this thread. As you
mention, there is the problem of evaluating the body of
the operator (of type Memory -> Value) repeated times for
the same memory, making the solution ineficient. Then
you sugest making the sharing explicit in the code. That
works for sharing in the same function definition. The
biggest problem with that is that when you do that, you
substitute the operators by their implementation:

  x .+. y .+. y

becomes

  let vx = x mem; vy = y mem
  in  vx + vy + vy
      ^^^^^^^^^^^^

That is possible in your example because you know the
implementation of the operator .+.

  (.+.) a b = \mem -> a mem + b mem

What about complex operator definitions hidden in the
implementation module of the library? This technique is
not feasible for them.

Romildo
-- 
Prof. José Romildo Malaquias <romildo@iceb.ufop.br>
Departamento de Computação
Universidade Federal de Ouro Preto
Brasil