Re[2]: strict Haskell dialect

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
41 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re[2]: strict Haskell dialect

Bulat Ziganshin
Hello Wolfgang,

Friday, February 03, 2006, 1:46:56 AM, you wrote:

>> i had one idea, what is somewhat corresponding to this discussion:
>>
>> make a strict Haskell dialect. implement it by translating all
>> expressions of form "f x" into "f $! x" and then going to the standard
>> (lazy) haskell translator. the same for data fields - add to all field
>> definitions "!" in translation process. then add to this strict
>> Haskell language ability to _explicitly_ specify lazy fields and lazy
>> evaluation, for example using this "~" sign
>>
>> what it will give? ability to use Haskell as powerful strict language,
>> what is especially interesting for "real-world" programmers. i have
>> found myself permanently fighting against the lazyness once i starting to
>> optimize my programs. for the newcomers, it just will reduce learning
>> path - they don't need to know anything about lazyness

WJ> Since laziness often allows you to solve problems so elegantly, I'm really
WJ> scared of the idea of a "Strict Haskell"! :-(  Is laziness really so "unreal"
WJ> that real-world programmers have to see it as an enemy which they have to
WJ> fight against?

WJ> In fact, I was kind of shocked as I read in Simon Peyton Jones' presentation
WJ> "Wearing the hair shirt" [1] that in his opinion "Lazyness doesn't really
WJ> matter".

i suggest you to write some large program like darcs and try to make
it as efficient as C++ ones. i'm doing sort of it, and i selected
Haskell primarily because it gives unprecedented combination of power
and safety due to its strong but expressive type system, higher-order
functions and so on. i also use benefits of lazyness from time to
time, and may be even don't recognize each occasion of using lazyness.
but when i'm going to optimize my program, when i'm asking myself "why
it is slower than C counterparts?", the answer is almost exclusively
"because of lazyness". for example, i now wrote I/O library. are you
think that i much need lazyness here? no, but that i really need is
the highest possible speed, so now i'm fighting against lazyness even
more than usual :)

well, 80% of any program don't need optimization at all. but when i
write remaining 20% or even 5%, i don't want to fight against
something that can be easily fixed in systematic way. all other
widespread languages have _optional_, explicitly stated lazyness in
form of callable blocks, even the Omega goes in this way. and i'm
interested in playing with such Haskell dialect in order to see how my
programming will change if i need to explicitly specify lazyness when
i need it, but have strictness implicitly. i think that newcomers from
other languages who wants to implement real projects instead of
experimenting will also prefer strict Haskell

you may hear that last days Haskell become one of fastest language in
the Shootout. why? only because all those programs was rewritten to be
strict. it was slow and hard process. and adding preprocessor that
makes all code strict automagically will allow to write efficient
Haskell programs without reading fat manuals

each laguage feature has its time. 15 years ago i could substantially
speed up C program by rewriting it in asm. Now the C compilers in most
cases generate better code than i can. moreover, strict FP languages
now are ready to compete with gcc. But lazy languages are still not
compiled so efficient that they can be used for time-critical code.
so, if we don't want to wait another 10 years, we should implement
easier ways to create strict programs. if you think that lazy
programming is great, you can show this in shootout or by showing me
the way to optimize code of my real programs. i'm open to new
knowledge :)

--
Best regards,
 Bulat                            mailto:[hidden email]



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
Bulat Ziganshin wrote:

> Hello Wolfgang,
>
> Friday, February 03, 2006, 1:46:56 AM, you wrote:
>>> i had one idea, what is somewhat corresponding to this discussion:
>>>
>>> make a strict Haskell dialect. implement it by translating all
>>> expressions of form "f x" into "f $! x" and then going to the
>>> standard (lazy) haskell translator. the same for data fields - add
>>> to all field definitions "!" in translation process. then add to
>>> this strict
>>> Haskell language ability to _explicitly_ specify lazy fields and
>>> lazy evaluation, for example using this "~" sign

[Apologies for replying to a reply of a reply but I don't seem to have
received the original post]

I've been thinking along these lines too, because it has always seemed to me
that laziness is just a real nuisance because it hides a lot of inefficiency
under the carpet as well as making the time/space behaviour of programs
difficult to understand...

One question is how to get some kind of "do" notation that would work well
in a strict setting.
The existing "do" notation makes use of lazyness in so far as the second arg
of  >> is only evaluated when needed. Perhaps a new keyword such as "go"
could be used to use >>= instead ie:

go {e1;e2;e3}   ===           e1 >>= (\_-> (e2 >>= (\_->e3)))

Of course this doesn't solve the problem of how to translate programs that
make heavy use of mapM etc.

I wonder: is monadic programming really dependent on lazyness or is there a
realistic (ie not impossibly complicated) way to use monads in a strict
setting?

A related question is: could monadic programming ever be as efficient as
side-effect programming?

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Jan-Willem Maessen

On Feb 3, 2006, at 2:33 PM, Brian Hulley wrote:

> Bulat Ziganshin wrote:
>> Hello Wolfgang,
>>
>> Friday, February 03, 2006, 1:46:56 AM, you wrote:
>>>> i had one idea, what is somewhat corresponding to this discussion:
>>>>
>>>> make a strict Haskell dialect. implement it by translating all
>>>> expressions of form "f x" into "f $! x" and then going to the
>>>> standard (lazy) haskell translator. the same for data fields - add
>>>> to all field definitions "!" in translation process. then add to
>>>> this strict
>>>> Haskell language ability to _explicitly_ specify lazy fields and
>>>> lazy evaluation, for example using this "~" sign
>
> [Apologies for replying to a reply of a reply but I don't seem to  
> have received the original post]
>
> I've been thinking along these lines too, because it has always  
> seemed to me that laziness is just a real nuisance because it hides  
> a lot of inefficiency under the carpet as well as making the time/
> space behaviour of programs difficult to understand...

I pointed out some problems with strict Haskell in a recent talk, but  
I think it'd be worth underscoring them here in this forum.

First off, I should mention that I was one of the main implementors  
of pH, which had Haskell's syntax, but used eager evaluation.  So  
what I'm about to say is based on my experience with Haskell code  
which was being eagerly evaluated.

There is one very difficult piece of syntax in a strict setting: The  
*where* clause.  The problem is that it's natural to write a bunch of  
bindings in a where clause which only scope over a few conditional  
clauses.  I'm talking about stuff like this:

f x
   | p x               = ..... a ...a . a .... a ...
   | complex_condition = ......... b .. b ... b ......
   | otherwise         = ..... a ....... b .....
   where a = horrible expression in x which is bottom when  
complex_condition is true.
         b = nasty expression in x which doesn't terminate when p x  
is true.
         complex_condition = big expression which
                              goes on for lines and lines
                              and would drive the reader
                              insane if it occurred in line.

Looks pretty reasonable, right?  Not when you are using eager or  
strict evaluation.  I think a strict variant of Haskell would either  
end up virtually where-free (with tons of lets instead---a pity as I  
often find where clauses more readable) or the semantics of where  
would need to change.

This came up surprisingly more often than I expected, though it was  
hardly a universal problem.  The more "interesting" the code, the  
more likely there would be trouble in my experience.

A bunch of other stuff would have to be added, removed, or modified.  
The use of lists as generators would need to be re-thought (and  
probably discarded), idioms involving infinite lists would have to  
go, etc., etc.  But this is a simple matter of libraries (well, and  
which type(s) get(s) to use square brackets as special builtin  
notation).

-Jan-Willem Maessen
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

haskell-2
In reply to this post by Brian Hulley
Brian Hulley wrote:

> > ...
>
> [Apologies for replying to a reply of a reply but I don't seem to have
> received the original post]
>
> I've been thinking along these lines too, because it has always seemed
> to me that laziness is just a real nuisance because it hides a lot of
> inefficiency under the carpet as well as making the time/space behaviour
> of programs difficult to understand...
>
> One question is how to get some kind of "do" notation that would work
> well in a strict setting.
> The existing "do" notation makes use of lazyness in so far as the second
> arg of  >> is only evaluated when needed. Perhaps a new keyword such as
> "go" could be used to use >>= instead ie:
>
> go {e1;e2;e3}   ===           e1 >>= (\_-> (e2 >>= (\_->e3)))
>
> Of course this doesn't solve the problem of how to translate programs
> that make heavy use of mapM etc.
>
> I wonder: is monadic programming really dependent on lazyness or is
> there a realistic (ie not impossibly complicated) way to use monads in a
> strict setting?
>
> A related question is: could monadic programming ever be as efficient as
> side-effect programming?
>
> Regards, Brian.

What about writing functions in a modified form of Control.Monad.Identity that
ensures the return value that forces the return values:

> module Control.Monad.Strict (Weak,mkWeak,unsafeMkWeak,runWeak,
>                              Deep,mkDeep,unsafeMkDeep,runDeep) where

Weak uses seq to achieve WHNF for it's argument

> newtype Weak a = WeakCon {runWeak :: a}
> mkWeak x = seq x (WeakCon x)
> unsafeMkWeak x = WeakCon x
>
> instance Functor Weak where
>     fmap f w = mkWeak (f (runWeak w))
>
> instance Monad Weak where
>     return x = mkWeak x
>     w >>= f = f (runWeak w)
>

I can't make the deepSeq version typecheck:

Deep uses deepSeq to evaluate it's argument

> newtype Deep a = DeepCon {runDeep :: a}
> mkDeep x = deepSeq x (DeepCon a)
> unsafeDeep x = DeepCon x
>
> instance Functor Deep where
>     fmap f d = mkDeep (f (runDeep d))
>
> instance Monad Deep where
>     return d = mkDeep d
>     d >>= f = f (runDeep d)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

haskell-2
In reply to this post by Brian Hulley
Brian Hulley wrote:
> Bulat Ziganshin wrote:

> [Apologies for replying to a reply of a reply but I don't seem to have
> received the original post]
>
> I've been thinking along these lines too, because it has always seemed
> to me that laziness is just a real nuisance because it hides a lot of
> inefficiency under the carpet as well as making the time/space behaviour
> of programs difficult to understand...
>
> One question is how to get some kind of "do" notation that would work
> well in a strict setting.
> The existing "do" notation makes use of lazyness in so far as the second
> arg of  >> is only evaluated when needed. Perhaps a new keyword such as
> "go" could be used to use >>= instead ie:
>
> go {e1;e2;e3}   ===           e1 >>= (\_-> (e2 >>= (\_->e3)))
>
> Of course this doesn't solve the problem of how to translate programs
> that make heavy use of mapM etc.
>
> I wonder: is monadic programming really dependent on lazyness or is
> there a realistic (ie not impossibly complicated) way to use monads in a
> strict setting?
>
> A related question is: could monadic programming ever be as efficient as
> side-effect programming?
>
> Regards, Brian.
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


What about writing functions in a modified form of Control.Monad.Identity that
ensures the return value that forces the return values:

> module Control.Monad.Strict (Weak,mkWeak,unsafeMkWeak,runWeak,
>                              Deep,mkDeep,unsafeMkDeep,runDeep) where

Weak uses seq to achieve WHNF for it's argument

> newtype Weak a = WeakCon {runWeak :: a}
> mkWeak x = seq x (WeakCon x)
> unsafeMkWeak x = WeakCon x
>
> instance Functor Weak where
>     fmap f w = mkWeak (f (runWeak w))
>
> instance Monad Weak where
>     return x = mkWeak x
>     w >>= f = f (runWeak w)
>

I can't make the deepSeq version typecheck:

Deep uses deepSeq to evaluate it's argument

> newtype Deep a = DeepCon {runDeep :: a}
> mkDeep x = deepSeq x (DeepCon a)
> unsafeDeep x = DeepCon x
>
> instance Functor Deep where
>     fmap f d = mkDeep (f (runDeep d))
>
> instance Monad Deep where
>     return d = mkDeep d
>     d >>= f = f (runDeep d)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

greenrd
In reply to this post by Brian Hulley
On Fri, 3 Feb 2006 19:33:12 -0000
"Brian Hulley" <[hidden email]> wrote:

> I've been thinking along these lines too, because it has always
> seemed to me that laziness is just a real nuisance because it hides a
> lot of inefficiency under the carpet as well as making the time/space
> behaviour of programs difficult to understand...
>
> One question is how to get some kind of "do" notation that would work
> well in a strict setting.
> The existing "do" notation makes use of lazyness in so far as the
> second arg of  >> is only evaluated when needed. Perhaps a new
> keyword such as "go" could be used to use >>= instead ie:
>
> go {e1;e2;e3}   ===           e1 >>= (\_-> (e2 >>= (\_->e3)))

That's not necessary. >> has something in common with if', where

if' True x _ = x
if' False _ y = y

- in both cases, it makes sense to evaluate the arguments lazily.

So simply make strictness the default and have laziness annotations
(for arguments), instead of making laziness the default and having
strictness annotations.

> A related question is: could monadic programming ever be as efficient
> as side-effect programming?

Monads can be viewed as code generators. So, with partial
evaluation, my guess is yes, at least in many important cases.
--
Robin
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

John Meacham
In reply to this post by Brian Hulley
On Fri, Feb 03, 2006 at 07:33:12PM -0000, Brian Hulley wrote:
> One question is how to get some kind of "do" notation that would work well
> in a strict setting.
> The existing "do" notation makes use of lazyness in so far as the second
> arg of  >> is only evaluated when needed. Perhaps a new keyword such as
> "go" could be used to use >>= instead ie:

you can override (>>) in your monad

instance Monad ... where
        a >> b = a `seq` b `seq` (a >>= \_ -> b)
        ....

unless I am misunderstanding what you want.

        John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Jan-Willem Maessen
Jan-Willem Maessen wrote:

> I pointed out some problems with strict Haskell in a recent talk, but
> I think it'd be worth underscoring them here in this forum.

Is the text of this talk or points raised in it available online anywhere?

> <snip> There is one very difficult piece of syntax in a strict setting:
> The
> *where* clause.  The problem is that it's natural to write a bunch of
> bindings in a where clause which only scope over a few conditional
> clauses.  I'm talking about stuff like this:
>
> f x
>   | p x               = ..... a ...a . a .... a ...
>   | complex_condition = ......... b .. b ... b ......
>   | otherwise         = ..... a ....... b .....
>   where a = horrible expression in x which is bottom when
> complex_condition is true.
>         b = nasty expression in x which doesn't terminate when p x
> is true.
>         complex_condition = big expression which
>                              goes on for lines and lines
>                              and would drive the reader
>                              insane if it occurred in line.

Surely it would not be too difficult for the compiler to only evaluate the
where bindings that are relevant depending on which guard evaluates to True
ie in your example, the binding for a would be evaluated if p x is True,
otherwise the complex_condition would be evaluated, and if True, b would be
evaluated, otherwise a and b would be evaluated:

f x
     | p x = let a = ..... in ....a a ...
     | otherwise = let
                                 complex_condition = ...
                                 b = ...
                          in
                                if complex_condition then
                                       .... b .... b
                               else let
                                             a = ..... a
                                      in
                                            .... a.....b

where all the messy (possibly duplicated) let's are generated by the
compiler so the user can still use the nice where syntax.

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by greenrd
Robin Green wrote:

> On Fri, 3 Feb 2006 19:33:12 -0000
> "Brian Hulley" <[hidden email]> wrote:
>> I've been thinking along these lines too, because it has always
>> seemed to me that laziness is just a real nuisance because it hides a
>> lot of inefficiency under the carpet as well as making the time/space
>> behaviour of programs difficult to understand...
>>
>> One question is how to get some kind of "do" notation that would work
>> well in a strict setting.
>> The existing "do" notation makes use of lazyness in so far as the
>> second arg of  >> is only evaluated when needed. Perhaps a new
>> keyword such as "go" could be used to use >>= instead ie:
>>
>> go {e1;e2;e3}   ===           e1 >>= (\_-> (e2 >>= (\_->e3)))
>
> That's not necessary. >> has something in common with if', where
>
> if' True x _ = x
> if' False _ y = y
>
> - in both cases, it makes sense to evaluate the arguments lazily.
>
> So simply make strictness the default and have laziness annotations
> (for arguments), instead of making laziness the default and having
> strictness annotations.

Where would you put these laziness annotations?
If you put them in the function declaration eg as in:

     if' :: ~a -> ~b -> Bool

presumably you'd want the compiler to pass the args as thunks instead of
evaluated values. However this means that all args to every function would
have to be passed as thunks, even though for strict functions these thunks
would immediately be evaluated. The problem is that there is no way for the
compiler to optimize out the thunk creation / evaluation step because it
occurs across the "black box" of a function call, thus we wouldn't get the
same efficiency as in a language such as ML where no thunks are created in
the first place.

Ie there is a fundamental asymmetry between lazy annotations and strict
annotations - it is trivial to go from lazy to strict before the function
body is evaluated but impossible to unevaluate from strict back to lazy...

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by John Meacham
John Meacham wrote:

> On Fri, Feb 03, 2006 at 07:33:12PM -0000, Brian Hulley wrote:
>> One question is how to get some kind of "do" notation that would
>> work well in a strict setting.
>> The existing "do" notation makes use of lazyness in so far as the
>> second arg of  >> is only evaluated when needed. Perhaps a new
>> keyword such as "go" could be used to use >>= instead ie:
>
> you can override (>>) in your monad
>
> instance Monad ... where
>         a >> b = a `seq` b `seq` (a >>= \_ -> b)
>         ....
>
> unless I am misunderstanding what you want.
>
>         John

If strictness was the default (eg if the language were ML not Haskell), then
in

             putStr "hello" >> putStr (show 1)

both args to >> would be evaluated before >> was called. Thus putStr (show
1) would be evaluated before the combined monad is actually run, which would
be wasteful if we were using a monad with a >> function that only runs the
rhs conditionally on the result of the lhs.
If Haskell were a strict language I think an equivalent for the do notation
would have to lift everything (except the first expression) and use >>=
instead of >> .

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Brian Hulley
Brian Hulley wrote:
>     if' :: ~a -> ~b -> Bool
Oooops :-)

          if' :: Bool -> ~a -> ~a -> a

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Brian Hulley
Brian Hulley wrote:

> Robin Green wrote:
>> <snip>
>> So simply make strictness the default and have laziness annotations
>> (for arguments), instead of making laziness the default and having
>> strictness annotations.
>
> Where would you put these laziness annotations?
> If you put them in the function declaration eg as in:
>
>     if' :: Bool -> ~a -> ~a -> a                       [corrected]
>
> presumably you'd want the compiler to pass the args as thunks instead
> of evaluated values. However this means that all args to every
> function would have to be passed as thunks, even though for strict
> functions these thunks would immediately be evaluated. The problem is
> that there is no way for the compiler to optimize out the thunk
> creation / evaluation step because it occurs across the "black box"
> of a function call, thus we wouldn't get the same efficiency as in a
> language such as ML where no thunks are created in the first place.

I'm just soooo slow!!! ;-) Of course the laziness info would now be part of
the function's type so the compiler would be able to generate the correct
code to prepare thunks or evaluated values before calling the function. So
your idea of laziness annotations for args would give the best of both
worlds :-)

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: strict Haskell dialect

Ben Rudiak-Gould
In reply to this post by haskell-2
Chris Kuklewicz wrote:
> Weak uses seq to achieve WHNF for it's argument
>
>> newtype Weak a = WeakCon {runWeak :: a}
>> mkWeak x = seq x (WeakCon x)
>> unsafeMkWeak x = WeakCon x

This doesn't actually do what you think it does. mkWeak and unsafeMkWeak are
the same function.

     mkWeak 123 = seq 123 (WeakCon 123) = WeakCon 123
     unsafeMkWeak 123 = WeakCon 123
     mkWeak _|_ = seq _|_ (WeakCon _|_) = _|_
     unsafeMkWeak _|_ = WeakCon _|_ = _|_

To quote John Meacham:

| A quick note,
| x `seq` x
| is always exactly equivalant to x. the reason being that your seq
| would never be called to force x unless x was needed anyway.
|
| I only mention it because for some reason this realization did not hit
| me for a long time and once it did a zen-like understanding of seq
| (relative to the random placement and guessing method I had used
| previously) suddenly was bestowed upon me.

I remember this anecdote because when I first read it, a zen-like
understanding of seq suddenly was bestowed upon /me/. Maybe it should be in
the docs. :-)

-- Ben

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: strict Haskell dialect

haskell-2
What I wanted to make was a Deep / DeepCon Monad which called deepSeq or some
strategy.  But I could not make it type check.

Ben Rudiak-Gould wrote:

> Chris Kuklewicz wrote:
>> Weak uses seq to achieve WHNF for it's argument
>>
>>> newtype Weak a = WeakCon {runWeak :: a}
>>> mkWeak x = seq x (WeakCon x)
>>> unsafeMkWeak x = WeakCon x
>
> This doesn't actually do what you think it does. mkWeak and unsafeMkWeak
> are the same function.
>
>     mkWeak 123 = seq 123 (WeakCon 123) = WeakCon 123
>     unsafeMkWeak 123 = WeakCon 123
>     mkWeak _|_ = seq _|_ (WeakCon _|_) = _|_
>     unsafeMkWeak _|_ = WeakCon _|_ = _|_
>
> To quote John Meacham:
>
> | A quick note,
> | x `seq` x
> | is always exactly equivalant to x. the reason being that your seq
> | would never be called to force x unless x was needed anyway.
> |
> | I only mention it because for some reason this realization did not hit
> | me for a long time and once it did a zen-like understanding of seq
> | (relative to the random placement and guessing method I had used
> | previously) suddenly was bestowed upon me.
>
> I remember this anecdote because when I first read it, a zen-like
> understanding of seq suddenly was bestowed upon /me/. Maybe it should be
> in the docs. :-)
>
> -- Ben
>

Yeah, that was silly.  Falling back to `seq` was useless.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Jan-Willem Maessen
In reply to this post by Brian Hulley

On Feb 3, 2006, at 8:16 PM, Brian Hulley wrote:

> Jan-Willem Maessen wrote:
>
>> I pointed out some problems with strict Haskell in a recent talk, but
>> I think it'd be worth underscoring them here in this forum.
>
> Is the text of this talk or points raised in it available online  
> anywhere?
>
>> <snip> There is one very difficult piece of syntax in a strict  
>> setting: The
>> *where* clause.  The problem is that it's natural to write a bunch of
>> bindings in a where clause which only scope over a few conditional
>> clauses.  I'm talking about stuff like this:
>>
>> f x
>>   | p x               = ..... a ...a . a .... a ...
>>   | complex_condition = ......... b .. b ... b ......
>>   | otherwise         = ..... a ....... b .....
>>   where a = horrible expression in x which is bottom when
>> complex_condition is true.
>>         b = nasty expression in x which doesn't terminate when p x
>> is true.
>>         complex_condition = big expression which
>>                              goes on for lines and lines
>>                              and would drive the reader
>>                              insane if it occurred in line.
>
> Surely it would not be too difficult for the compiler to only  
> evaluate the where bindings that are relevant depending on which  
> guard evaluates to True ie in your example, the binding for a would  
> be evaluated if p x is True, otherwise the complex_condition would  
> be evaluated, and if True, b would be evaluated, otherwise a and b  
> would be evaluated: ...

In principle, yes, this is eminently doable.  But the translation  
becomes surprisingly messy when the bindings in question are mutually  
recursive.  Certainly it's not a simple syntax-directed translation,  
in contrast to essentially every other piece of syntactic sugar in  
the language.

-Jan-Willem Maessen

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Re[2]: strict Haskell dialect

Bulat Ziganshin
In reply to this post by Brian Hulley
Hello Brian,

Saturday, February 04, 2006, 4:50:44 AM, you wrote:

>>> One question is how to get some kind of "do" notation that would
>>> work well in a strict setting.
>>> The existing "do" notation makes use of lazyness in so far as the
>>> second arg of  >> is only evaluated when needed. Perhaps a new
>>> keyword such as "go" could be used to use >>= instead ie:

BH> If strictness was the default (eg if the language were ML not Haskell), then
BH> in

BH>              putStr "hello" >> putStr (show 1)

BH> both args to >>> would be evaluated before >> was called. Thus putStr (show
BH> 1) would be evaluated before the combined monad is actually run, which would
BH> be wasteful if we were using a monad with a >> function that only runs the
BH> rhs conditionally on the result of the lhs.
BH> If Haskell were a strict language I think an equivalent for the do notation
BH> would have to lift everything (except the first expression) and use >>=
BH> instead of >>> .

it seems that you misunderstand the monads (or may be i misunderstand :)

each and every monadic operation is a function! type "IO a" is really
"RealWorld -> (RealWorld,a)" and the same for any other monad. concept
of the monad by itself means carrying "hidden" state from one monadic
operation to the next. that allows to _order_ monadic operations plus
this state used for zillions other things, including state, logs,
fails and so on, so on


--
Best regards,
 Bulat                            mailto:[hidden email]



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Brian Hulley
Brian Hulley wrote:

> Brian Hulley wrote:
>> Robin Green wrote:
>>> <snip>
>>> So simply make strictness the default and have laziness annotations
>>> (for arguments), instead of making laziness the default and having
>>> strictness annotations.
>>
>> Where would you put these laziness annotations?
>> If you put them in the function declaration eg as in:
>>
>>     if' :: Bool -> ~a -> ~a -> a                       [corrected]
>>
>> presumably you'd want the compiler to pass the args as thunks instead
>> of evaluated values. However this means that all args to every
>> function would have to be passed as thunks, even though for strict
>> functions these thunks would immediately be evaluated. The problem is
>> that there is no way for the compiler to optimize out the thunk
>> creation / evaluation step because it occurs across the "black box"
>> of a function call, thus we wouldn't get the same efficiency as in a
>> language such as ML where no thunks are created in the first place.
>
> I'm just soooo slow!!! ;-) Of course the laziness info would now be
> part of the function's type so the compiler would be able to generate
> the correct code to prepare thunks or evaluated values before calling
> the function. So your idea of laziness annotations for args would
> give the best of both worlds :-)

For an eager language, a state monad could perhaps be defined by

          data ST m a = ST ~(m -> (m,a))

and the other operations would work as normal without any additional
annotations. (?)

I must admit I'm a bit confused as to why the strictness annotations in
Haskell (and Clean) are only allowed in data declarations and not function
declarations, since it seems a bit random to have to guess which args can be
evaluated strictly at the call site although it of course gives flexibility
(eg to use (+) strictly or lazily). The type system doesn't prevent someone
from writing (>>) m0 $! m1 even though the author of (>>) may have been
relying on m1 being lazily evaluated... (?)

For an eager language, it would seem that lazy annotations would have to be
allowed as part of a function's type so that if' could be implemented. Does
anyone know of a type system that incorporates lazy annotations, and/or how
these would be propagated?

What would the signature of a lazy map function be?

             map :: (~a -> ~b) -> ~[a] -> ~[b]
             map :: (a -> b) -> ~[~a~] -> ~[b~]

                etc etc - quite a puzzle!!!

Thanks, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Tomasz Zielonka
On Sun, Feb 05, 2006 at 05:18:55PM -0000, Brian Hulley wrote:
> I must admit I'm a bit confused as to why the strictness annotations in
> Haskell (and Clean) are only allowed in data declarations and not function
> declarations

Clean does allow strictness annotations in function types.

Best regards
Tomasz

--
I am searching for programmers who are good at least in
(Haskell || ML) && (Linux || FreeBSD || math)
for work in Warsaw, Poland
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Bulat Ziganshin
Bulat Ziganshin wrote:

> Hello Brian,
>
> Saturday, February 04, 2006, 4:50:44 AM, you wrote:
>
>>>> One question is how to get some kind of "do" notation that would
>>>> work well in a strict setting.
>>>> The existing "do" notation makes use of lazyness in so far as the
>>>> second arg of  >> is only evaluated when needed. Perhaps a new
>>>> keyword such as "go" could be used to use >>= instead ie:
>
>> If strictness was the default (eg if the language were ML not
>> Haskell), then in
>
>>              putStr "hello" >> putStr (show 1)
>
>> both args to >>> would be evaluated before >> was called. Thus
>> putStr (show 1) would be evaluated before the combined monad is
>> actually run, which would be wasteful if we were using a monad with
>> a >> function that only runs the rhs conditionally on the result of
>> the lhs.
>> If Haskell were a strict language I think an equivalent for the do
>> notation would have to lift everything (except the first expression)
>> and use >>= instead of >>> .
>
> it seems that you misunderstand the monads (or may be i misunderstand
> :)
>
> each and every monadic operation is a function! type "IO a" is really
> "RealWorld -> (RealWorld,a)" and the same for any other monad. concept
> of the monad by itself means carrying "hidden" state from one monadic
> operation to the next. that allows to _order_ monadic operations plus
> this state used for zillions other things, including state, logs,
> fails and so on, so on

exp1 >> exp2 in a strict setting would force exp1 to be evaluated to a
monad, exp2 to be evaluated to a monad, then these monads to be combined
using >> into another monad, which at some later point would actually be
run. But it is this eager evaluation of exp2 into the rhs monad that is the
problem, because in the example above, (show 1) would be evaluated during
the evaluation of (putStr "hello" >> putStr (show 1)) whereas in Haskell it
would only be evaluated when the combined monad is actually run (because it
is only at this point that Haskell actually creates the combined monad from
the thunk).

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re[2]: strict Haskell dialect

Brian Hulley
In reply to this post by Tomasz Zielonka
Tomasz Zielonka wrote:
> On Sun, Feb 05, 2006 at 05:18:55PM -0000, Brian Hulley wrote:
>> I must admit I'm a bit confused as to why the strictness annotations
>> in Haskell (and Clean) are only allowed in data declarations and not
>> function declarations
>
> Clean does allow strictness annotations in function types.

Thanks for pointing this out - I must admit I had only taken a very quick
look at Clean (I was overwhelmed by the complicated type system) but now
I've found the place in the Clean book that describes strictness annotations
for function types so I must look into this a bit more.

If I wanted to write a 3d computer game in Haskell (or Clean), would lazy
evaluation with strictness annotations lead to as fast a program as eager
evaluation with lazy annotations for the same amount of programming effort?
And would the result be as fast as an equivalent program in C++ or OCaml or
MLton? If so, there would obviously be no point wasting time trying to
develop an eager dialect of Haskell (or Clean).

I wonder if current compilation technology for lazy Haskell (or Clean) has
reached the theoretical limits on what is possible for the compiler to
optimize away, or if it is just that optimization has not received so much
attention as work on the type system etc?

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
123