[Haskell-cafe] Re: OPPS, missing attachment (was Re: howto mix <- within do?

Larry Evans cppljevans at suddenlink.net
Fri Oct 17 11:56:40 EDT 2008

On 10/17/08 08:12, Daniel Fischer wrote:

Thanks very much Daniel.

> Am Freitag, 17. Oktober 2008 14:42 schrieb Larry Evans:
>> On 10/17/08 07:39, Larry Evans wrote:
>>> The attached code produces error:
>>> <-- cut here --
>> [snip]
>> {- 
>> Purpose:
>>   Explore how to mix 'assignments' inside do.
>> Motivation:
>>   Instead of:
>>     let 
>>       { v0 = e0
>>       ; v1 = e1 
>>       }
>>     in do
>>       { print v0
>>       ; print v1
>>       }
>>   which is hard to read, recode above as:
>>     do
>>       { v0 = e0
>>       ; print v0
>>       ; v1 = e1
>>      ; print v1
>>       }
> That would have to be
> do let v0 = e0
>    print v0
>    let v1 = e1
>    print v1
> or
> do v0 <- return e0
>    print v0
>    v1 <- return e1
>    print v1
> (better (?):
> do print $ e0
>    print $ e1
> )

At first, the |let v = e| combination looked best (less typing).
However, my actual e0 was more complicated:

       [ Expr   <== Op0 GramOne
       , Term   <== Op0 GramOne
       , Factor <== Op0 GramOne

where <== was a binary operator which just produced a tuple pair.
I wanted to keep the expression on multiple lines because it's
easier to read.  The <== was defined to make the expression
look more like grammar productions (the Op0 GramOne is not
the final rhs.  That's only for testing purposes.).

Unfortunately, using let with the multiline rhs failed to
compile (due, I guess, to some layout rules, which I find
difficult to fathom).  So, I tried the | v <- return e|
combination.  This worked although I had to surround e with
parenthesis to enable compilation with multiple lines:

   ; gram_eqs::GramEqs ArithInp ArithVar <- return
       [ Expr   <== Op0 GramOne
       , Term   <== Op0 GramOne
       , Factor <== Op0 GramOne
   ; putStr "gram_eqs="
   ; print gram_eqs

I didn't use the last combination |print $ e0|
because e1 may use v0.  IOW:

   v0 <- return e0
   v1 <- return ...v0...

>>   which is easier to read and more intuitive for
>>   c++ programmers.
> "intuitive for c++ programmers" is dangerous, the languages are very 
> different, and one shouldn't gloss over that. The different syntax should 
> help to not confound the languages.

OK, but I'm finding it very difficult to figure out how to do
something that's very simple in c++:

   ; calculate e0
   ; store e0 in v0
   ; print v0
   ; calculate e1 using possibly v0
   ; store e1 in v1
   ; print v1

However, apparently, in haskell, the operands on each side of the ';'
must be "compatible".  Hmmm, I remember seeing a translation of
more complex haskell statments/expression to simpler ones...


Mea culpa :(  I should have read that first.  Then
a would have realized:

   (v0 <- e0) >> putStr "v0"

would not have worked because, I guess:

   e0 >> putStr "v0"

would not work. OOPS, sect3.14 has a specialization on the pattern p<-e.
That specialization is harder to understand.  I'll work on it :)

> remember that in
> do value <- action
>    statements -- using value (or not)
> action and statements must belong to the same monad. In your code above, the 
> 'action' [999] has type Num a => [a], so the monad is [], but putStr "v0=" 
> has type IO (), the monad is IO. So the binding v0 <- [999] and the statement 
> putStr "v0=" can't appear in the same do-block.
> If what you want is "for every member of some list, do some monadic action", 
> you need mapM/mapM_ resp forM(_):

Nope.  I just want to trace through various stages in translation of
a language grammar(a set of "grammar equationss") to a corresponding
set of equations defining the lookahead sets for that grammar.
So, I want the do{...} to just be a sequence of (calculate value; print 
value} where calculate value may use previously calculated values).

Thanks for you help.


More information about the Haskell-Cafe mailing list