Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Andrew Coppin

Jonathan Cast wrote:

On Fri, 2008-08-29 at 20:56 +0100, Andrew Coppin wrote:
  
I've been playing with this today, and no matter what rules I come up 
with, it seems to be ridiculously easy to put the interpretter into an 
infinite loop from which it will never escape. Is there any way to know 
which binds are worth expanding and which ones aren't? (I have a 
sinking feeling this might be equivilent to the Halting Problem...)


For example, if you have let x = f y; y = g x in x then since all the 
functions are free variables, there's really nothing much useful you 
can do to simplify this any further. However, my interpretter merrily 
goes into an endless loop building a huge expression like f (g (f (g (f 
(g... Is it possible to avoid this?



If you want to avoid infinite normal forms (or just plain lack of normal
forms, as in let x = x in x or (\x - x x) (\ x - x x)), you need to
follow three rules:

1) Static typing
2) No value recursion
3) If you allow data types, no recursive data types

Otherwise, your language will be Turing-complete, so yes, trying to
determine ahead of time if even a HNF exists will be the halting
problem.

If you really want to write a general-purpose evaluator, then infinite
normal forms may not be an issue, as long as they are generated lazily,
so your evaluator can at least print something out while it goes into an
infinite loop.  Otherwise, you can declare f x, where f is an unknown
function, a HNF, and stop at that point, or go on only under the
client's control.

The optimizers used by GHC and YHC pick one function out of each
recursive binding group, and just refuse to inline it at all.  If you
don't mind producing expressions that aren't really in any definable
HNF, that would be an alternative as well.
  


Right. So if I have, say, the factorial function defined using the Y 
combinator, there's no way to stop the interpretter expanding an 
infinite number of copies of Y, even though in theory the factorial 
function should terminate?


Oh well, I guess I'll just have to live with that one. Maybe I can make 
the binding to expand user-selectable or something...


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Ryan Ingram
On Sun, Aug 31, 2008 at 12:46 AM, Andrew Coppin
[EMAIL PROTECTED] wrote:
 Right. So if I have, say, the factorial function defined using the Y
 combinator, there's no way to stop the interpretter expanding an infinite
 number of copies of Y, even though in theory the factorial function should
 terminate?

Well, this is exactly what ghci is doing; you just have to choose an
evaluation order that makes sense.

Lets consider a simple translation for recursive lets:
 let x = exp1 in exp2
(where x may be free in exp1 and/or exp2)

Here's a simple translation into lambda-calculus:
 (\x. exp2) (y (\x. exp1))

(Of course, this representation for let can lose sharing; without
knowing what you have or your goals I don't know if you care).

Now, you just have to choose a y-combinator that makes sense for your
evaluation order.  If you do normal-order evaluation like Haskell
(non-strict), this Y should work for you:

y = \f. (\x. f (x x)) (\x. f (x x))

 Oh well, I guess I'll just have to live with that one. Maybe I can make the
 binding to expand user-selectable or something...

Now, if you are eagerly-expanding the entire expression, trying to get
to head normal form, then any expression that ends up with y in it
won't terminate.  But if you use normal form evaluation order, then if
a normal form exists, you will find it and terminate.

So evaluating fact to normal form won't terminate, but evaluating
fact 5 should.

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Calling Lockheed, Indra, Thales, Raytheon

2008-08-31 Thread Jason Dusek
  You could dump the archives, grep out the names and then
  Google...

--
_jsn
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Adrian Hey

Dan Doel wrote:

Here's a first pass:

-- snip --

{-# LANGUAGE Rank2Types, GeneralizedNewtypeDeriving #-}

module Unique where

import Control.Monad.Reader
import Control.Monad.Trans

import Control.Concurrent.MVar

-- Give Uniques a phantom region parameter, so that you can't accidentally
-- compare Uniques from two different uniqueness sources.
newtype Unique r = Unique Integer deriving Eq

newtype U r a = U { unU :: ReaderT (MVar Integer) IO a }
  deriving (Functor, Monad, MonadIO)

-- Higher rank type for region consistency
runU :: (forall r. U r a) - IO a
runU m = newMVar 0 = runReaderT (unU m)

newUnique :: U r (Unique r)
newUnique = U (do source - ask
  val - lift $ takeMVar source
  let next = val + 1
  lift $ putMVar source next
  return $ Unique next)

-- hashUnique omitted

-- snip --

It's possible that multiple unique sources can exist in a program with this 
implementation, but because of the region parameter, the fact that a Unique 
may not be globally unique shouldn't be a problem. If your whole program 
needs arbitrary access to unique values, then I suppose something like:


main = runU realMain

realMain :: U r ()
realMain = ...

is in order.

Insert standard complaints about this implementation requiring liftIO all over 
the place if you actually want to do other I/O stuff inside the U monad.


Well that wouldn't be my main complaint :-)

Thanks for taking the time to do this Dan. I think the safety
requirement has been met, but I think it fails on the improved API.
The main complaint would be what I see as loss of modularity, in that
somehow what should be a small irrelevant detail of the implementation
of some obscure module somewhere has propogated it's way all the way
upto main.

This is something it seems to have in common with all other attempts
I've seen to solve the global variable problem without actually using
a..you know what :-) It doesn't matter whether it's explicit state
handle args, withWhateverDo wrappers, novel monads or what. They
all have this effect.

To me this seems completely at odds with what I thought was generally
accepted wisdom of how to write good maintainable, modular software.
Namely hiding as much implemention detail possible and keeping APIs
as simple and stable as they can be. I don't know if I'm alone in
that view nowadays.

I'm also not sure I understand why so many people seem to feel that
stateful effects must be accounted for somehow in the args and/or
types of the effecting function. Like if I had..

getThing :: IO Thing

..as an FFI binding, nobody would give it a moments thought. They'd
see it from it's type that it had some mysterious world state
dependent/effecting behaviour, but would be quite happy to just
accept that the didn't really need to worry about all that magic...
instead they'd accept that it just works.

Why then, if I want to implement precisely the same thing in Haskell
(using a global variable) does it suddenly become so important for
this stateful magic to be accounted for? Like the presence of that
global variable must be made so very painfully apparent in main
(and everywhere else on the dependency path too I guess).

In short, I just don't get it :-)

Purists aren't going to like it, but I think folk *will* be using real
global variables in I/O libs for the forseeable future. Seems a shame
that they'll have to do this with unsafePerformIO hack though :-(

Regards
--
Adrian Hey

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sat, 30 Aug 2008, Ashley Yakeley wrote:

OK. Let's call it top-level scope. Haskell naturally defines such a 
thing, regardless of processes and processors. Each top-level - would 
run at most once in top-level scope.


If you had two Haskell runtimes call by C code, each would have its own 
memory allocator and GC; IORefs, Uniques and thunks cannot be shared 
between them; and each would have its own top-level scope, even though 
they're in the same process.


That sounds more feasible - though it does constrain a plugin 
architecture (in which Haskell code can dynamically load other Haskell 
code) to cooperate with the loading RTS and not load multiple copies of 
modules; this might make linking tricky. There's also the problem Duncan 
Coutts mentioned about loading multiple versions of the same module - what 
are the semantics of - in relation to that?


Also, it's no use for mediating access to a resource or library that can 
only be accessed once, right? In fact, even without the problem of two 
Haskell runtimes in one process this can't work, since some library in 
another language might also choose to access that resource or library.


What applications does this leave beyond Data.Unique and Random?

Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sat, 30 Aug 2008, Adrian Hey wrote:


Ganesh Sittampalam wrote:

Well, yes, but if I implemented a library in standard Haskell it would 
always be safely serialisable/deserialisable (I think). So the global 
variables hack somehow destroys that property - how do I work out why it 
does in some cases but not others?


This has nothing to do with the use of global variables. If you have
a set of values that are guaranteed to be distinct (unique) and you
add another random/arbitrary value to that set you have no way of
knowing that it is different from any current member (other than
searching the entire set, assuming it's available).


OK, never mind about this. I was thinking that referential transparency 
was violated by remoting, but since unique values can only be constructed 
in IO, I think I was wrong.



Well, I've never seen a convincing use case for global variables :-)


Well apart from all the libs that couldn't be implemented with them...


They can't be implemented with an interface that is completely oblivious 
to the fact that the libraries require some state.


Dynamic loading and plugins work fine with standard Haskell now, because 
nothing in standard Haskell breaks them. The - proposal might well break 
them, which is a significant downside for it.


I don't see how, but if so - bindings are not the cause of the
brokeness. They'd still be broken using the unsafePerformIO hack.


Which places the unsafePerformIO hack at fault, seeing as it's unsafe and 
a hack and all :-) If - was standard then it'd be up to everyone else to 
work round its limitations.


In general, the smaller the world that the Haskell standard lives in, the 
less it can interfere with other concerns. - massively increases that 
world, by introducing the concept of a process scope.


All IORefs,MVars,Chans scope across the entire process defined by main.
Or at least they *should*, if they don't then something is already
badly wrong somewhere. This has nothing to do with whether or not they
appear at top level. This is what an IORef/MVar whatever is defined to
be.


Their scope is where they can be used, and this is something we can 
explicitly track by inspecting the program text. If they are just used in 
one part of the program, their scope is limited to that part of the 
program.



But then again, I'm sure that some that will be adamant that any way
of making global variables is a hack. But they'll still be happy
to go on using file IO, sockets etc regardless, blissfully unaware
of the hacks they are dependent on :-)


I'm not sure of precisely what you mean here, but stdin, stdout and stderr 
are things provided by the OS to a process. That's what defines them as 
having process scope, not something the Haskell language or RTS does.


Those rules aren't actually strong enough to provide a guarantee of 
process level scope.


The rules for - bindings shouldn't have to guarantee this.
This should be guaranteed by newMVar returning a new *MVar*, wherever
it's used (for example).


The issue is whether the - is run multiple times in a single process or 
not, rather than how the thing it calls behaves.



I mean semantic faults, as in the proposal just doesn't do what it
promises for some subtle reason.


It doesn't provide once-only semantics across an entire process in cases 
involving dynamic loading or two Haskell libraries together with RTS 
separately linked into the same C program. I don't know whether you intend 
that it does promise that or not, but it seems to be necessary for many of 
the applications that are used to justify it.


If you consider not giving you thread local variables a fault I guess 
you're entitled to that view, but this was never the intent of the 
proposal in the first place (that's not what people are trying to do 
when they use the unsafePerformIO hack).


The thread-local variables point was a relatively minor issue for me 
compared to the dynamic loading and related issues.


Cheers,

Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 10:20, Ganesh Sittampalam wrote:

On Sat, 30 Aug 2008, Adrian Hey wrote:

But then again, I'm sure that some that will be adamant that any way

of making global variables is a hack. But they'll still be happy
to go on using file IO, sockets etc regardless, blissfully unaware
of the hacks they are dependent on :-)


I'm not sure of precisely what you mean here, but stdin, stdout and  
stderr are things provided by the OS to a process. That's what  
defines them as having process scope, not something the Haskell  
language or RTS does.


But their representations in Haskell must have the same scope and are  
therefore de facto global variables.


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 10:20, Ganesh Sittampalam wrote:

I'm not sure of precisely what you mean here, but stdin, stdout and 
stderr are things provided by the OS to a process. That's what defines 
them as having process scope, not something the Haskell language or RTS 
does.


But their representations in Haskell must have the same scope and are 
therefore de facto global variables.


Yep, but this is not Haskell providing a way to make global variables, it 
is just providing an interface to ones that already exist. The point is 
that the RTS can't provide (process-scope) global variables of its own 
invention, because it can't guarantee to be running at the top-level of a 
process, which it needs to be in order to control their construction.


Cheers,

Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 10:29, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:20, Ganesh Sittampalam wrote:
I'm not sure of precisely what you mean here, but stdin, stdout  
and stderr are things provided by the OS to a process. That's what  
defines them as having process scope, not something the Haskell  
language or RTS does.


But their representations in Haskell must have the same scope and  
are therefore de facto global variables.


Yep, but this is not Haskell providing a way to make global  
variables, it is just providing an interface to ones that already  
exist. The point is that the RTS can't provide (process-scope)


But that is done the same way as providing general global variables,  
so you can't get away from it.


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 10:29, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:20, Ganesh Sittampalam wrote:
I'm not sure of precisely what you mean here, but stdin, stdout and 
stderr are things provided by the OS to a process. That's what defines 
them as having process scope, not something the Haskell language or RTS 
does.


But their representations in Haskell must have the same scope and are 
therefore de facto global variables.


Yep, but this is not Haskell providing a way to make global variables, it 
is just providing an interface to ones that already exist. The point is 
that the RTS can't provide (process-scope)


But that is done the same way as providing general global variables, so you 
can't get away from it.


I don't follow what you mean. stdin, stdout and stderr are just file 
descriptors 0, 1 and 2, aren't they? You can create them as many times as 
you want with using that information without causing any confusion or 
conflict. Whereas the - proposal has a once-only requirement.


Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 10:34, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:29, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:20, Ganesh Sittampalam wrote:
I'm not sure of precisely what you mean here, but stdin, stdout  
and stderr are things provided by the OS to a process. That's  
what defines them as having process scope, not something the  
Haskell language or RTS does.
But their representations in Haskell must have the same scope and  
are therefore de facto global variables.
Yep, but this is not Haskell providing a way to make global  
variables, it is just providing an interface to ones that already  
exist. The point is that the RTS can't provide (process-scope)


But that is done the same way as providing general global  
variables, so you can't get away from it.


I don't follow what you mean. stdin, stdout and stderr are just file  
descriptors 0, 1 and 2, aren't they? You can create them as many  
times as you want with using that information without causing any  
confusion or conflict. Whereas the - proposal has a once-only  
requirement.


The convention is to provide buffered versions to improve the  
performance of file I/O.  These buffered filehandles must be created  
once per runtime instance (and ideally once per process so multiple  
runtimes don't find themselves overwriting each others' output).


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Adrian Hey wrote:

Thanks for taking the time to do this Dan. I think the safety 
requirement has been met, but I think it fails on the improved API. The 
main complaint would be what I see as loss of modularity, in that 
somehow what should be a small irrelevant detail of the implementation 
of some obscure module somewhere has propogated it's way all the way 
upto main.


That's the key point, as I see it - they aren't irrelevant details of the 
implementation, they are requirements the implementation places on its 
context in order for that implementation to be correct. So they should be 
communicated appropriately.



To me this seems completely at odds with what I thought was generally
accepted wisdom of how to write good maintainable, modular software.
Namely hiding as much implemention detail possible and keeping APIs
as simple and stable as they can be. I don't know if I'm alone in
that view nowadays.


It's no problem to hide implementation detail, but I don't think you 
should hide the *requirement* of the implementation that it has 
constraints on how it is called, namely that it requires once-only 
initialisation or whatever.



Purists aren't going to like it, but I think folk *will* be using real
global variables in I/O libs for the forseeable future. Seems a shame
that they'll have to do this with unsafePerformIO hack though :-(


From a purist point of view, it's a shame that they choose to do it at 

all :-)

Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 10:34, Ganesh Sittampalam wrote:


I don't follow what you mean. stdin, stdout and stderr are just file 
descriptors 0, 1 and 2, aren't they? You can create them as many times as 
you want with using that information without causing any confusion or 
conflict. Whereas the - proposal has a once-only requirement.


The convention is to provide buffered versions to improve the performance of 
file I/O.  These buffered filehandles must be created once per runtime 
instance (and ideally once per process so multiple runtimes don't find 
themselves overwriting each others' output).


In that case it seems that any library that might be used from a runtime 
that isn't the top-level of a process should avoid doing IO to those 
handles, for fear of producing output corruption?


Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 10:44, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:34, Ganesh Sittampalam wrote:
I don't follow what you mean. stdin, stdout and stderr are just  
file descriptors 0, 1 and 2, aren't they? You can create them as  
many times as you want with using that information without causing  
any confusion or conflict. Whereas the - proposal has a once- 
only requirement.


The convention is to provide buffered versions to improve the  
performance of file I/O.  These buffered filehandles must be  
created once per runtime instance (and ideally once per process so  
multiple runtimes don't find themselves overwriting each others'  
output).


In that case it seems that any library that might be used from a  
runtime that isn't the top-level of a process should avoid doing IO  
to those handles, for fear of producing output corruption?



You handle it the same way you handle I/O with concurrency:  either  
one of the runtimes is privileged to the extent that it owns the  
filehandles and other runtimes must make an inter-runtime call to use  
them, or the filehandle structures include locking and are shared  
across runtimes.  Both of these are used in Haskell (see most GUI  
libraries for the former, and the implementation of Handles for the  
latter).


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Adrian Hey

Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Adrian Hey wrote:

Thanks for taking the time to do this Dan. I think the safety 
requirement has been met, but I think it fails on the improved API. 
The main complaint would be what I see as loss of modularity, in that 
somehow what should be a small irrelevant detail of the implementation 
of some obscure module somewhere has propogated it's way all the way 
upto main.


That's the key point, as I see it - they aren't irrelevant details of 
the implementation, they are requirements the implementation places on 
its context in order for that implementation to be correct. So they 
should be communicated appropriately.


Eh? Please illustrate your point with Data.Unique. What requirements
does it place on it's context? (whatever that might mean :-)

It just does what it says on the tin AFAICS. There are no requirements
it places on clients (to use an OO term), as should any halfway
decent API IMO.


To me this seems completely at odds with what I thought was generally
accepted wisdom of how to write good maintainable, modular software.
Namely hiding as much implemention detail possible and keeping APIs
as simple and stable as they can be. I don't know if I'm alone in
that view nowadays.


It's no problem to hide implementation detail, but I don't think you 
should hide the *requirement* of the implementation that it has 
constraints on how it is called, namely that it requires once-only 
initialisation or whatever.


No decent API should require this. Data.Unique certainly doesn't.
In fact is debatable whether any API should requre an initalisation
call at all before other stuff should be called (the other stuff
check initialisation has occured and do it itself if necessary).

The real irony of your remark is that making APIs this robust is
practically impossible *without* using global variables, and you're
now saying that because they've done this work to eliminate these
constraints they now have to be held to account for this with
an absurd API.

Seems like a clear case of no good deed going unpunished :-)

Regards
--
Adrian Hey

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 11:20, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 10:44, Ganesh Sittampalam wrote:
In that case it seems that any library that might be used from a  
runtime that isn't the top-level of a process should avoid doing  
IO to those handles, for fear of producing output corruption?


You handle it the same way you handle I/O with concurrency:  either  
one of the runtimes is privileged to the extent that it owns the  
filehandles and other runtimes must make an inter-runtime call to  
use them, or the filehandle structures include locking and are  
shared across runtimes.  Both of these are used in Haskell (see  
most GUI libraries for the former, and the implementation of  
Handles for the latter).


Where do the filehandle structures live in the latter case?



The place you clearly think so little of that you need to ask:   
process-global (or process-local depending on how you think about it)  
storage.  And everything in that storage must have locking.  (And this  
requirement makes it similar in some ways to other non-directly- 
accessible process state such as (say) the process id.)


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 11:20, Ganesh Sittampalam wrote:



Where do the filehandle structures live in the latter case?


The place you clearly think so little of that you need to ask: 
process-global (or process-local depending on how you think about it) 
storage.  And everything in that storage must have locking.


I'm sorry if this makes me seem ignorant, but I'd never heard of such a 
thing before. What is the API for accessing such storage, and/or where can 
I find its documentation?


Cheers,

Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Adrian Hey wrote:


Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Adrian Hey wrote:

Thanks for taking the time to do this Dan. I think the safety requirement 
has been met, but I think it fails on the improved API. The main complaint 
would be what I see as loss of modularity, in that somehow what should be 
a small irrelevant detail of the implementation of some obscure module 
somewhere has propogated it's way all the way upto main.


That's the key point, as I see it - they aren't irrelevant details of the 
implementation, they are requirements the implementation places on its 
context in order for that implementation to be correct. So they should be 
communicated appropriately.


Eh? Please illustrate your point with Data.Unique. What requirements
does it place on it's context? (whatever that might mean :-)


It requires that its context initialises it precisely once.

Data.Unique is actually a poor example, as it is actually fine to 
initialise it multiple times as long as the resulting Unique values aren't 
treated as coming from the same datatype. But equally it can be 
implemented with IORefs, so it's not a good advert for the need for global 
variables.



The real irony of your remark is that making APIs this robust is
practically impossible *without* using global variables, and you're
now saying that because they've done this work to eliminate these
constraints they now have to be held to account for this with
an absurd API.


I think there are two cases to consider here.

A Data.Unique style library, which requires genuinely *internal* state, 
and which is agnostic to having multiple copies of itself loaded 
simultaneously. In that case, there is no requirement for a process-level 
scope for -, just that each instance of the library is only initialised 
once - the RTS can do this, as can any dynamic loader.


The other is some library that really cannot be safely loaded multiple 
times, because it depends on some lower-level shared resource. Such a 
library simply cannot be made safe without cooperation from the thing that 
controls that shared resource, because you cannot prevent a second copy of 
it being loaded by something you have no control over.


If the - proposal were only about supporting the first of these 
applications, I would have far fewer objections to it. But it would have 
nothing to do with process-level scope, then.


Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 12:01, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 11:20, Ganesh Sittampalam wrote:

Where do the filehandle structures live in the latter case?


The place you clearly think so little of that you need to ask:  
process-global (or process-local depending on how you think about  
it) storage.  And everything in that storage must have locking.



You'll have to look at specific implementations.  One that I can think  
of off the top of my head is Perl 5's ithreads; there is a  
distinguished allocation store which is global to all ithreads, and  
the interpreter instance gives you primitives for locking and mutexing  
(see use threads::shared;).


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Andrew Coppin

Ryan Ingram wrote:

On Sun, Aug 31, 2008 at 12:46 AM, Andrew Coppin
[EMAIL PROTECTED] wrote:
  

Right. So if I have, say, the factorial function defined using the Y
combinator, there's no way to stop the interpretter expanding an infinite
number of copies of Y, even though in theory the factorial function should
terminate?



Well, this is exactly what ghci is doing; you just have to choose an
evaluation order that makes sense.

Lets consider a simple translation for recursive lets:
  

let x = exp1 in exp2


(where x may be free in exp1 and/or exp2)

Here's a simple translation into lambda-calculus:
  

(\x. exp2) (y (\x. exp1))



(Of course, this representation for let can lose sharing; without
knowing what you have or your goals I don't know if you care).

Now, you just have to choose a y-combinator that makes sense for your
evaluation order.  If you do normal-order evaluation like Haskell
(non-strict), this Y should work for you:

y = \f. (\x. f (x x)) (\x. f (x x))

  

Oh well, I guess I'll just have to live with that one. Maybe I can make the
binding to expand user-selectable or something...



Now, if you are eagerly-expanding the entire expression, trying to get
to head normal form, then any expression that ends up with y in it
won't terminate.  But if you use normal form evaluation order, then if
a normal form exists, you will find it and terminate.

So evaluating fact to normal form won't terminate, but evaluating
fact 5 should.
  


All of this strongly suggests that if you execute things in the correct 
order, you can arrange it so that expressions that have a normal form 
will be evaluated to it. But how to decide the correct evaluation order? 
For the plain lambda calculus, IIRC you just have to execute the 
left-most, outer-most redex every time and it'll work. For a language 
with let-binds, it is unclear to me how to proceed...


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 12:01, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 11:20, Ganesh Sittampalam wrote:

Where do the filehandle structures live in the latter case?


The place you clearly think so little of that you need to ask: 
process-global (or process-local depending on how you think about it) 
storage.  And everything in that storage must have locking.



You'll have to look at specific implementations.  One that I can think of off 
the top of my head is Perl 5's ithreads; there is a distinguished 
allocation store which is global to all ithreads, and the interpreter 
instance gives you primitives for locking and mutexing (see use 
threads::shared;).


From what I can see from the source of this, it seems to rely on a global 
variable inside the Perl library that contains a pointer to the shared 
state area (actually a separate Perl interpreter of its own, but that's 
just an implementation detail). However I may be wrong as I was unable to 
fully figure out how the BOOT: mechanism works from a simple grep.


I'm afraid I don't see how this generalises to sharing something across an 
entire process where the things that want to do the sharing are not in or 
controlled by the same shared library. In particular the filehandle 
structures required for buffered I/O need to be common to every single 
piece of code in the process that might want to use them, no matter what 
language or language implementation that code uses.


Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Jonathan Cast
On Sun, 2008-08-31 at 17:29 +0100, Andrew Coppin wrote:
 Ryan Ingram wrote:
  On Sun, Aug 31, 2008 at 12:46 AM, Andrew Coppin
  [EMAIL PROTECTED] wrote:

  Right. So if I have, say, the factorial function defined using the Y
  combinator, there's no way to stop the interpretter expanding an infinite
  number of copies of Y, even though in theory the factorial function should
  terminate?
  
 
  Well, this is exactly what ghci is doing; you just have to choose an
  evaluation order that makes sense.
 
  Lets consider a simple translation for recursive lets:

  let x = exp1 in exp2
  
  (where x may be free in exp1 and/or exp2)
 
  Here's a simple translation into lambda-calculus:

  (\x. exp2) (y (\x. exp1))
  
 
  (Of course, this representation for let can lose sharing; without
  knowing what you have or your goals I don't know if you care).
 
  Now, you just have to choose a y-combinator that makes sense for your
  evaluation order.  If you do normal-order evaluation like Haskell
  (non-strict), this Y should work for you:
 
  y = \f. (\x. f (x x)) (\x. f (x x))
 

  Oh well, I guess I'll just have to live with that one. Maybe I can make the
  binding to expand user-selectable or something...
  
 
  Now, if you are eagerly-expanding the entire expression, trying to get
  to head normal form, then any expression that ends up with y in it
  won't terminate.  But if you use normal form evaluation order, then if
  a normal form exists, you will find it and terminate.
 
  So evaluating fact to normal form won't terminate, but evaluating
  fact 5 should.

 
 All of this strongly suggests that if you execute things in the correct 
 order, you can arrange it so that expressions that have a normal form 
 will be evaluated to it. But how to decide the correct evaluation order? 
 For the plain lambda calculus, IIRC you just have to execute the 
 left-most, outer-most redex every time and it'll work. For a language 
 with let-binds, it is unclear to me how to proceed...

It depends on whether you want to preserve sharing or not.  If not, you
can use fix to de-sugar lambdas, and then de-sugar lets using the rule

  let x = e in f
= (\ x - f) e

and proceed as before.  Or (again, if you don't care about sharing), you
can descend recursively into the body of a let, remembering where the
bindings were defined, and expand variables when you see them.

Or keep an environment around, extend it on let, and if the left-most
outermost redex is a variable, look it up.

jcc


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Ryan Ingram
On Sun, Aug 31, 2008 at 9:29 AM, Andrew Coppin
[EMAIL PROTECTED] wrote:
 All of this strongly suggests that if you execute things in the correct
 order, you can arrange it so that expressions that have a normal form will
 be evaluated to it. But how to decide the correct evaluation order? For the
 plain lambda calculus, IIRC you just have to execute the left-most,
 outer-most redex every time and it'll work. For a language with let-binds,
 it is unclear to me how to proceed...

What are you trying to get from the let binding?  Sharing?

The usual idea is that let represents heap allocation, and you
evaluate the leftmost-outermost redex as usual, doing let substitution
only when necessary to continue evaluation, and garbage-collecting
bindings that no longer refer to variables in the current computation.
 You also make lambda-expressions create let-bindings during
substitution to maximize sharing.

Here's an example of how an interpreter could work:

let fact_acc = \n x. (== n 0) x (fact_acc (- n 1) (* n x))
in fact_acc 3 1

The top-level redex is a let bind that is already in WHNF; if it
wasn't, you continue evaluation inside of it.  So instead you
substitute and lose sharing because there are no other options.

I'm going to leave all previous lets as ... in this evaluation to
save typing:

(substitute because leftmost-outermost redex is a let-bind)
= let ... in (\n x. (== n 0) x (fact_acc (- n 1) (* n x))) 3 1
(beta, beta)
= let ...; n0 = 3; x0 = 1 in (== n0 0) x0 (fact_acc (- n0 1) (* n0 x0))
(primitive == is strict, n0 is already in normal form, evaluate ==)
= let ... in False x0 (fact_acc (- n0 1) (* n0 x0))
(False x y = y)
= let ... in fact_acc (- n0 1) (* n0 x0)
(substitute fact_acc, beta, beta)
= let ...; n1 = (- n0 1); x0 = (* n0 x0) in (== n1 0) x1 (fact_acc (-
n1 1) (* n1 x1))
(primitive == is strict, evaluate its argument.
 primitive - is strict, argument is in whnf, evaluate -)
(This is a very important step; note that I am now evaluating inside
of a let bind!)
= let ...; n1 = 2; ... in (== n1 0) x1 (fact_acc (- n1 1) (* n1 x1))
(evaluate ==)
= let ... in False x1 (fact_acc (- n1 1) (* n1 x1))
(False x y = y)
= let ... in fact_acc (- n1 1) (* n1 x1)
= let ...; n2 = (- n1 1); x2 = (* n1 x1) in (== n2 0) x2 (fact_acc (-
n2 1) (* n2 x2))
= let ...; n2 = 1; ... in (== n2 0) x2 (fact_acc (- n2 1) (* n2 x2))
= let ... in False x2 (fact_acc (- n2 1) (* n2 x2))
= let ... in fact_acc (- n2 1) (* n2 x2))
= let ...; n3 = (- n2 1); x3 = (* n2 x2) in (== n3 0) x3 (fact_acc (-
n3 1) (* n3 x3))
= let ...; n3 = 0; ... in (== n3 0) x3 (fact_acc (- n3 1) (* n3 x3))
= let ... in True x3 (fact_acc (- n3 1) (* n3 x3))
= let ... in x3
(We can garbage collect fact_acc and n3 here)
= let
  n0 = 3; x0 = 1;
  n1 = 2; x1 = (* n0 x0);
  n2 = 1; x2 = (* n1 x1);
  x3 = (* n2 x2) in x3
(primitive * is strict, so we get a big spine of evaluating x3 which
requires x2 which requires x1 which requires x0 which is finally
already in head normal form)
= let ...; x1 = (* 3 1); x2 = (* 2 x1); x3 = (* 1 x2) in x3
(garbage collect n0, n1, n2, n3)
= let x1 = 3; x2 = (* 2 x1); x3 = (* 1 x2) in x3
(substitute  garbage collect x1)
= let x2 = (* 2 3); x3 = (* 1 x2) in x3
= let x2 = 6; x3 = (* 1 x3) in x3
= let x3 = (* 1 6) in x3
= let x3 = 6 in x3
= 6

Does this seem like something you could do?

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Ryan Ingram
The point of having a strongly typed language is so the compiler can
do more work for you.  But right now I do a lot of typing (pun not
intended) to appease the compiler.

Let me give you an example:

module Prob where
import qualified Data.Map as M
...

newtype Prob p a = Prob { runProb :: [(a,p)] }

combine :: (Num p, Ord a) = Prob p a - Prob p a
combine m = Prob $
M.assocs $
foldl' (flip $ uncurry $ M.insertWith (+)) M.empty $
runProb m

Do you see it?  All those M. just seem dirty to me, especially
because the compiler should be able to deduce them from the types of
the arguments.

My proposal is to allow ad-hoc overloading of names; if a name is
ambiguous in a scope, attempt to type-check the expression against
each name.  It is only an error if type-checking against all names
fails.  If type-checking succeeds for more than one then the
expression is ambiguous and this is also an error.

Pros: shorter code, less busywork to please the compiler
Cons: potentially exponential compile time?

Any thoughts?

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: [Haskell] Compiler Construction course using Haskell?

2008-08-31 Thread Johan Jeuring

Dear Johannes,

Besides the IPT course, we also teach a course hat used to be called
grammars and parsing. This course is taken before the compiler
construction course. In this course we deal with parser combinators,
datatypes, folds, first and follow, LL(1), and some more stuff, all
in Haskell. The lecture notes are available from the webpage for the
course:

http://www.cs.uu.nl/docs/vakken/gont/literatuur.html

The web page is in Dutch, but the lecture notes are in English.

All the best,

Johan

On 20 Aug 2008, at 21:47, Johannes Waldmann wrote:


Thanks for all the pointers. This is very useful.

On parsers: yes, LL/LR theory and table-based parsers have been
developed for a reason and it's no easy decision to throw them out.
Still, even Parsec kind of computes the FIRST sets?

And - I positively hate preprocessors.
I really want my domain specific languages embedded
because I want to use Haskell's types, functions, modules etc.
for the domain specific objects (parsers, AST walkers, etc.)

Best regards, J.W.



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Daniel Fischer
Am Sonntag, 31. August 2008 20:21 schrieb Ryan Ingram:
 The point of having a strongly typed language is so the compiler can
 do more work for you.  But right now I do a lot of typing (pun not
 intended) to appease the compiler.

 Let me give you an example:

 module Prob where
 import qualified Data.Map as M
 ...

 newtype Prob p a = Prob { runProb :: [(a,p)] }

 combine :: (Num p, Ord a) = Prob p a - Prob p a
 combine m = Prob $
 M.assocs $
 foldl' (flip $ uncurry $ M.insertWith (+)) M.empty $
 runProb m

 Do you see it?  All those M. just seem dirty to me, especially
 because the compiler should be able to deduce them from the types of
 the arguments.

 My proposal is to allow ad-hoc overloading of names; if a name is
 ambiguous in a scope, attempt to type-check the expression against
 each name.  It is only an error if type-checking against all names
 fails.  If type-checking succeeds for more than one then the
 expression is ambiguous and this is also an error.

 Pros: shorter code, less busywork to please the compiler
 Cons: potentially exponential compile time?

 Any thoughts?

   -- ryan

Another Con is that the compiler can catch fewer programming errors that way. 
I can't think of a credible example right now, but what if you typo'd a 
function argument, it typechecks according to the above rules, but with a 
completely unintended function and your programme outputs garbage (of course, 
garbage which is not immediately recognisable as such)?

Still, I often have the same desire when I forget a qualification :)

Cheers,
Daniel

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Johannes Waldmann

 My proposal is to allow ad-hoc overloading of names; 

+1, although ...

this could interact badly with the (still common?)
practice of leaving out type declarations.
(of course having allowed this in the first place
is another language design error :-)

when considering language changes (extensions),
we should carefully distinguish whether it mainly
helps readability or writability - and readability
should be the prime concern.

e.g. ad-hoc overloading will lead to less typing,
but more trouble reading.

often, the work of typing can be reduced by tools
(e.g. IDEs that know about the names that are currently in scope,
and are applicable for a particular type,
and can auto-complete them etc.)

in the particular case of writing M.* too often,
another option would be to have a local unqualification
of an import. Cf. C++: using namespace, which can occur
in any scope, not just at top (module) level;  or Ada: use.

J.W.





signature.asc
Description: OpenPGP digital signature
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Bulat Ziganshin
Hello Ryan,

Sunday, August 31, 2008, 10:21:44 PM, you wrote:

 Cons: potentially exponential compile time?

yes, and exponential programming complexity growth, going to brain explosion :)

don't forget that OOP languages that supports ad-hoc overloading
doesn't allow to infer types in both directions. it seems that we
should trade one feature for another


-- 
Best regards,
 Bulatmailto:[EMAIL PROTECTED]

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Andrew Coppin

Ryan Ingram wrote:

What are you trying to get from the let binding?  Sharing?
  


Convinience.

 let x = foo in bar

is so much easier to write than

 (\x - bar) foo

when foo and/or bar is large.

Trouble is, as soon as you allow let-bindings, some clever person is 
going to start writing recursive ones. And actually, that's a useful 
thing to be able to do, but it makes figuring out the technical 
details... rather nontrivial. (Seriously, I had no idea I was going to 
get into this much trouble!)

The usual idea is that let represents heap allocation, and you
evaluate the leftmost-outermost redex as usual, doing let substitution
only when necessary to continue evaluation, and garbage-collecting
bindings that no longer refer to variables in the current computation


Right. So ignore the let-bindings unless the redex of interest is a 
let-bound variable? That sounds reasonably easy...


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 14:58, Daniel Fischer wrote:

Am Sonntag, 31. August 2008 20:21 schrieb Ryan Ingram:

Do you see it?  All those M. just seem dirty to me, especially
because the compiler should be able to deduce them from the types of
the arguments.

Another Con is that the compiler can catch fewer programming errors  
that way.


If omitting the qualifier doesn't cause this already then I don't  
think it will be much of a problem (either it won't find what you're  
looking for or it will be ambiguous).


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Miguel Mitrofanov
Well, I was thinking that way when I was starting learning Haskell.  
But then I realized that this feature would make code much harder to  
read. Suppose you have different thing all named insertWith. You've  
got one somewhere in your program; how do YOU know when looking at the  
code after a month or so, which one is this? Certainly, given a smart  
IDE you can ask it; but I think that code should be clear just when  
you look at it, without any action.


What CAN be useful is, IMHO, to make your IDE substitute this M.s  
for you when you type.


On 31 Aug 2008, at 22:21, Ryan Ingram wrote:


The point of having a strongly typed language is so the compiler can
do more work for you.  But right now I do a lot of typing (pun not
intended) to appease the compiler.

Let me give you an example:

module Prob where
import qualified Data.Map as M
...

newtype Prob p a = Prob { runProb :: [(a,p)] }

combine :: (Num p, Ord a) = Prob p a - Prob p a
combine m = Prob $
   M.assocs $
   foldl' (flip $ uncurry $ M.insertWith (+)) M.empty $
   runProb m

Do you see it?  All those M. just seem dirty to me, especially
because the compiler should be able to deduce them from the types of
the arguments.

My proposal is to allow ad-hoc overloading of names; if a name is
ambiguous in a scope, attempt to type-check the expression against
each name.  It is only an error if type-checking against all names
fails.  If type-checking succeeds for more than one then the
expression is ambiguous and this is also an error.

Pros: shorter code, less busywork to please the compiler
Cons: potentially exponential compile time?

Any thoughts?

 -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Andrew Coppin

Ryan Ingram wrote:

My proposal is to allow ad-hoc overloading of names; if a name is
ambiguous in a scope, attempt to type-check the expression against
each name.  It is only an error if type-checking against all names
fails.  If type-checking succeeds for more than one then the
expression is ambiguous and this is also an error.

Pros: shorter code, less busywork to please the compiler
Cons: potentially exponential compile time?

Any thoughts?
  


Now try importing something like Data.Map where almost every single 
function name clashes with the Prelude. If I write


 foo x = map (bar x)

then unless there are some explicit type signatures somewhere, the poor 
compiler has no way of knowing whether this function is mapping over a 
list or a Map.


(Arguably you might wish to write a function that does both. This 
quickly boils down to an argument along the lines of Haskell doesn't 
support container neutrality very well, which as I understand it is 
already a known problem.)


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Gwern Branwen
On 2008.08.31 11:21:44 -0700, Ryan Ingram [EMAIL PROTECTED] scribbled 1.0K 
characters:
 The point of having a strongly typed language is so the compiler can
 do more work for you.  But right now I do a lot of typing (pun not
 intended) to appease the compiler.

 Let me give you an example:

 module Prob where
 import qualified Data.Map as M

 newtype Prob p a = Prob { runProb :: [(a,p)] }

 combine :: (Num p, Ord a) = Prob p a - Prob p a
 combine m = Prob $
 M.assocs $
 foldl' (flip $ uncurry $ M.insertWith (+)) M.empty $
 runProb m

 Do you see it?  All those M. just seem dirty to me, especially
 because the compiler should be able to deduce them from the types of
 the arguments.

 My proposal is to allow ad-hoc overloading of names; if a name is
 ambiguous in a scope, attempt to type-check the expression against
 each name.  It is only an error if type-checking against all names
 fails.  If type-checking succeeds for more than one then the
 expression is ambiguous and this is also an error.

 Pros: shorter code, less busywork to please the compiler
 Cons: potentially exponential compile time?

 Any thoughts?

   -- ryan

I think this would be very nice in GHCi, because there the situation is even 
*worse*.

I think we've all experienced importing Data.Map or Data.ByteString and 
discovering we need to tediously write it out in *full*, because we can't even 
do qualified imports of it!

--
gwern
BND fritz FKS 1071 Face government Tomahawk DREO IA O


signature.asc
Description: Digital signature
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Andrew Coppin

Gwern Branwen wrote:

I think this would be very nice in GHCi, because there the situation is even 
*worse*.

I think we've all experienced importing Data.Map or Data.ByteString and 
discovering we need to tediously write it out in *full*, because we can't even 
do qualified imports of it!
  


Amen to that!

Data.ByteString.Lazy.pack Hello  Data.ByteString.Lazy.++ 
Data.ByteString.Lazy.pack World!


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Cleaning up the Debian act (report from the trenches)

2008-08-31 Thread Magnus Therning
On Wed, Aug 27, 2008 at 10:20 PM, David Bremner [EMAIL PROTECTED] wrote:

 Ketil Malde wrote:

Another Debian question, once I've populated the debian/ directory one
way or another, how should this be integrated with the rest of the
project?  Should it be part of the darcs archive, or a separate
archive (foo-debian), or what?  How do people organize this?

 [EMAIL PROTECTED] is a good place for generic debian
 packaging questions.  After you have a package which works, and which
 hopefully lintian (a tool for checking debian packages) does not
 complain about, you can ask on debian-mentors for a sponsor, who will
 check over the package and hopefully upload it. Right now there is not
 too much interest in uploading new packages, because people are trying
 to get lenny out the door.

I've personally had _very_ limited success in getting any haskell
packages (both libs and apps) to attract any interest on
debian-mentors.  This is very unfortunate.  I suspect this is due to
haskell being an unknown language to most people on that list, and I
also suspect that the rather strict (but completely called for) rules
about dependencies and versions for haskell packages are unknown to
most DDs.  I've long thought that the DDs who are on debian-haskell
are in an excellent position to  change all of this, but I've never
pushed very much on this.

I've only ever gotten a single comment on an RFS for a haskell
package.  The comment was scary looking package
(http://lists.debian.org/debian-mentors/2007/10/msg00389.html).

AFAICS there is great room for improvement here, but this conversation
should probably move to debian-haskell or debian-mentor...

/M
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Miguel Mitrofanov

Erm... Why can't we?

On 1 Sep 2008, at 00:43, Gwern Branwen wrote:


I think we've all experienced importing Data.Map or Data.ByteString  
and discovering we need to tediously write it out in *full*, because  
we can't even do qualified imports of it!


--
gwern
BND fritz FKS 1071 Face government Tomahawk DREO IA O
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Miguel Mitrofanov

Oh, sorry, haven't noticed you said ghcI.

On 1 Sep 2008, at 00:59, Miguel Mitrofanov wrote:


Erm... Why can't we?

On 1 Sep 2008, at 00:43, Gwern Branwen wrote:


I think we've all experienced importing Data.Map or Data.ByteString  
and discovering we need to tediously write it out in *full*,  
because we can't even do qualified imports of it!


--
gwern
BND fritz FKS 1071 Face government Tomahawk DREO IA O
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Gwern Branwen
On 2008.09.01 01:01:21 +0400, Miguel Mitrofanov [EMAIL PROTECTED] scribbled 
0.5K characters:
 Oh, sorry, haven't noticed you said ghcI.

 On 1 Sep 2008, at 00:59, Miguel Mitrofanov wrote:

 Erm... Why can't we?

The GHC API just doesn't support it. See the bug report filed on this issue: 
http://hackage.haskell.org/trac/ghc/ticket/1895.

(Remember, each cc is like a vote!)

--
gwern
RX-7 PGP 5.0i ISFR Kosiura Reuters WANK mailbomb Templar NATIA


signature.asc
Description: Digital signature
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Stephan Friedrichs
Miguel Mitrofanov wrote:
 Suppose you have different thing all named insertWith. You've got one
 somewhere in your program; how do YOU know when looking at the code
 after a month or so, which one is this?

We already have that situation when classes are involved. If you replace
specialised functions by abstractions provided classes, for instance

mempty   instead of Data.Structure.empty
fmap instead of Data.Structure.map
folds from Data.Foldable instead of a specialised module

There certainly are more examples, but these are the most common.

IMHO this doesn't make code much harder to read. mempty gives us some
empty data structre, fmap applies a function to all its elements and
folds do the same. It doesn't matter if we're talking about lists, sets
or something else.

And it has the huge advantage that you can replace a data structure by
another (Maybe by [], [] by Set, ...) simply by changing a type
signature and not the code.

 Certainly, given a smart IDE you
 can ask it; but I think that code should be clear just when you look at
 it, without any action.

I think that - at least in the examples listed above - the code remains
very clear.

 
 [...]
 

Regards,
Stephan

-- 

Früher hieß es ja: Ich denke, also bin ich.
Heute weiß man: Es geht auch so.

 - Dieter Nuhr
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Compiler's bane

2008-08-31 Thread Jeremy Apthorp
2008/9/1 Andrew Coppin [EMAIL PROTECTED]:
 Ryan Ingram wrote:

 What are you trying to get from the let binding?  Sharing?


 Convinience.

  let x = foo in bar

 is so much easier to write than

  (\x - bar) foo

 when foo and/or bar is large.

 Trouble is, as soon as you allow let-bindings, some clever person is going
 to start writing recursive ones. And actually, that's a useful thing to be
 able to do, but it makes figuring out the technical details... rather
 nontrivial. (Seriously, I had no idea I was going to get into this much
 trouble!)

I'm confused -- why is this different to having recursive top-level bindings?

Jeremy
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Re: [Haskell] Top Level -

2008-08-31 Thread Ashley Yakeley

Ganesh Sittampalam wrote:

On Sat, 30 Aug 2008, Ashley Yakeley wrote:

OK. Let's call it top-level scope. Haskell naturally defines such a 
thing, regardless of processes and processors. Each top-level - would 
run at most once in top-level scope.


If you had two Haskell runtimes call by C code, each would have its 
own memory allocator and GC; IORefs, Uniques and thunks cannot be 
shared between them; and each would have its own top-level scope, even 
though they're in the same process.


That sounds more feasible - though it does constrain a plugin 
architecture (in which Haskell code can dynamically load other Haskell 
code) to cooperate with the loading RTS and not load multiple copies of 
modules; this might make linking tricky.


This is a good idea anyway. It's up to the dynamic loading architecture 
to get this right.


There's also the problem Duncan 
Coutts mentioned about loading multiple versions of the same module - 
what are the semantics of - in relation to that?


If they are different versions, they ought to be considered different 
modules with different names. Thus, Unique in base-3.0.2.0 ought to be a 
different type than Unique in base-4.0. Thus any top-level initialisers 
ought to be considered different and be run separately.


What's the current static behaviour? What happens if I link with 
packages B  C, which link with different versions of A?


Also, it's no use for mediating access to a resource or library that can 
only be accessed once, right? In fact, even without the problem of two 
Haskell runtimes in one process this can't work, since some library in 
another language might also choose to access that resource or library.


What applications does this leave beyond Data.Unique and Random?


So far we've just looked at declaring top-level IORefs and MVars.

By declaring top-level values of type IOWitness, you can generate open 
witnesses to any type, and thus solve the expression problem. See my 
open witness library and paper:

http://hackage.haskell.org/cgi-bin/hackage-scripts/package/open-witness
http://semantic.org/stuff/Open-Witnesses.pdf

--
Ashley Yakeley
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Claus Reinke
Well, I was thinking that way when I was starting learning Haskell.  
But then I realized that this feature would make code much harder to  
read. Suppose you have different thing all named insertWith. You've  
got one somewhere in your program; how do YOU know when looking at the  
code after a month or so, which one is this? Certainly, given a smart  
IDE you can ask it; but I think that code should be clear just when  
you look at it, without any action.


Indeed. Too much overloading can be a lot of trouble.

You can do adhoc overloading already:

   {-# LANGUAGE FlexibleInstances #-}

   class Adhoc a where adhoc :: a

   instance Adhoc ((a-b)-([a]-[b])) where adhoc = map
   instance Adhoc (Maybe a-a) where adhoc = maybe (error wrong 
number) id
   instance Adhoc [Char]   where adhoc = hello, world
   instance Adhoc (String-IO ())  where adhoc = print

   main :: IO ()
   main = adhoc (adhoc (adhoc . Just :: Char - Char) (adhoc :: String) :: 
String)

I hope this also demonstrates why it is usually a bad idea, even if
it often looks good in theory. If you're not convinced yet, play with
this kind of code in practice.

The well-typed programs don't go wrong of static type checking 
depends on a clear separation of right and wrong. If your use of

types allows anything to be a valid program, minor variations in code
will no longer be caught by the type system: at best, you'll get missing
instance, more likely you'll get too many possibilities, and at worst,
the code will simply do something different.

What CAN be useful is, IMHO, to make your IDE substitute this M.s  
for you when you type.


haskellmode for Vim does that (though it isn't type aware, so you
get a larger menu of possible completions than necessary).

Claus

[1] http://www.cs.kent.ac.uk/~cr3/toolbox/haskell/Vim/


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: vxml (validating xml lib) - maybe usable now, quadratic compilation time ?

2008-08-31 Thread Marc Weber
Oleg has pointed me into the right direction:
He has suggested to use kind of 
  class AttrOk elTrype attr 
for attributes (result 35s - 30s)
and do something similar with the state.
(30s - 4,5s).
After doing this I was quite happy:
The 4,5s do include reading the dtd and generating about 1500  DecQ
declarations.
There might still be some duplication.. in state transformation steps.
However trying to typecheck the same file repeating the body 400 times
didn't end.. why?

Have a quick glance at the file data which shows quadratic behaviour.
That's bad.. I would like to have some linear behaviour.
Any ideas what is causing this? Is there a way to get linear
scalability?
However disabling all validation stuff (see cabal flag) no longer
improves performance much. The data below proofs that right now
validation increases compilation time by a factor 1.35- 1.45
(within the range of 5-30 replications of the body)

If you'd like to play with the library and give some feedback
I'd be happy. Read the README.
The benchpress dependency is only needed for this benchmark test.
You may want to remove it from the cabal file.
So don't try to compile 4000 lines long xml files or be prepared to wait
days.
I should expand the benchmark to also offer results for xhtml lib.

Sincerly
Marc Weber

= compilation times with validation  
==

body replication count | compilation time [ms]

1 4146.477
2 4292.153
3 4508.56
4 4654.2441
5 4788.195
6 5041.6749
7 5347.11405
8 6134.59605
9 6019.6241
10 6459.544
11 7054.4339
12 7614.197
13 8489.003
14 8529.6109
15 9271.491
16 10058.419
17 12290.142
18 13736.0749
19 14863.893
20 15944.82
21 17856.6117
22 17977.841
23 17686.297
24 19279.314
25 20960.785
26 22750.754
27 24407.506
28 26342.242
29 28423.79
30 30932.7772
31 48478.841
32 45609.897
33 40574.255
34 41220.062
35 43952.5455
36 47437.922
37 50584.1210001
38 53983.8485
39 57935.593
=  ===
eg starting gnuplot
entering

f(x)=(x-b)**2*c+a
fit f(x) 'data' via a, b, c
plot 'data', f(x)

= compilation times without validation 

body replication count | compilation time [ms]

1 3939.887  Import.hs has been recompiled. thats why the first took longer 
then the next
2 3138.127
3 3080.317
4 3179.19
5 3279.339
6 3604.609
7 3736.829
8 4094.61795
9 4252.377
10 4767.588
11 5070.188
12 5537.007
13 5840.085
14 6478.276
15 6916.67
16 7568.444
17 8301.047
18 9211.3689
19 10025.886
20 10872.749
21 12086.263
22 12975.372
23 14366.282
24 15640.214
=  ===
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Top Level -

2008-08-31 Thread Brandon S. Allbery KF8NH

On 2008 Aug 31, at 13:20, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 12:01, Ganesh Sittampalam wrote:

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:

On 2008 Aug 31, at 11:20, Ganesh Sittampalam wrote:

Where do the filehandle structures live in the latter case?
The place you clearly think so little of that you need to ask:  
process-global (or process-local depending on how you think about  
it) storage.  And everything in that storage must have locking.


You'll have to look at specific implementations.  One that I can  
think of off the top of my head is Perl 5's ithreads; there is a  
distinguished allocation store which is global to all ithreads, and  
the interpreter instance gives you primitives for locking and  
mutexing (see use threads::shared;).


I'm afraid I don't see how this generalises to sharing something  
across an entire process where the things that want to do the  
sharing are not in or controlled by the same shared library. In  
particular the filehandle structures required for buffered I/O need  
to be common to every single piece of code in the process that might  
want to use them, no matter what language or language implementation  
that code uses.



For that you probably want to look at how ld.so.1 and libc interact to  
share the malloc pool and the stdin/stdout/stderr, among others.


--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon universityKF8NH


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Ryan Ingram
On Sun, Aug 31, 2008 at 2:10 PM, Claus Reinke [EMAIL PROTECTED] wrote:
 Indeed. Too much overloading can be a lot of trouble.

 You can do adhoc overloading already:

   {-# LANGUAGE FlexibleInstances #-}

   class Adhoc a where adhoc :: a

   instance Adhoc ((a-b)-([a]-[b])) where adhoc = map
   instance Adhoc (Maybe a-a) where adhoc = maybe (error wrong
 number) id
   instance Adhoc [Char]   where adhoc = hello, world
   instance Adhoc (String-IO ())  where adhoc = print

Yes, of course taken to this extent it is bad, but I'm not suggesting
this at all.  In particular, we have well-chosen names for many
functions, but not every container can use exact same interface (see,
for example, the many discussions on restricted monads).  So we
can't reuse the same function name for similar concepts that have
slightly different interfaces.

   main :: IO ()
   main = adhoc (adhoc (adhoc . Just :: Char - Char) (adhoc :: String) ::
 String)

 I hope this also demonstrates why it is usually a bad idea, even if
 it often looks good in theory. If you're not convinced yet, play with
 this kind of code in practice.

I do play with this kind of code in practice, in other languages.  In
practice, I don't see the kind of problems you are bringing up occur.
However, those languages tend to be dynamically typed so I do get the
occasional runtime type error.

I'd much rather have a safe way of doing less typing than an unsafe way.

As an example of this done correctly, in Ruby, you have
Array#each:
   [1,2,3].each { |x| print x }
Hash#each:
   { :foo = hello, :bar = world }.each { |k, v| print v }
etc.

each corresponds to the idea of iterating over a container (foldM in
Haskell) without being a slave to maintaining an identical API for
each type.

I maintain that in Haskell, trying to get this same generality often
leads to abuse of the typeclass system for things where the types
should trivially be determined at compile time.

 The well-typed programs don't go wrong of static type checking depends on
 a clear separation of right and wrong. If your use of
 types allows anything to be a valid program, minor variations in code
 will no longer be caught by the type system: at best, you'll get missing
 instance, more likely you'll get too many possibilities, and at worst,
 the code will simply do something different.

I don't think this is a strong argument.  In practice most things have
a single concrete type and helping the compiler with extra qualified
names is just meaningless typing.

I'm suggesting that in the case of this code:
 import Data.Map as M
 x = map (+1) M.empty
map should be inferred as M.map instead of being ambiguous.

There's already some minor work in the direction I am suggesting in
record syntax, but it only works during pattern matching.  I'd like
cx foo + cy foo to work on any foo that has record members cx and
cy that are members of Num, instead of needing to preface every record
with the datatype name to avoid ambiguity.

In particular I do NOT want each function in its own typeclass; the
previous post saying:
 foo x = map (bar x)
should be rejected as ambiguous without a type signature somewhere (at
least, if Data.Map is imported).  This does give some amount of
action at a distance where changing a file that is imported by
another file can cause previously unambiguous code to become
ambiguous, but that is already true!  And this modification would make
it less likely to be the case.

As to the argument that a sufficiently smart IDE would insert the
M. for me, I think that is flawed.  First, there isn't a
sufficiently smart IDE yet, and second, it'd be better for the
type-aware IDE to tell me the types of things when I (for example)
mouse over them, instead of helping me type longer things.

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Jonathan Cast
On Sun, 2008-08-31 at 16:08 -0700, Ryan Ingram wrote:
 In particular I do NOT want each function in its own typeclass; the
 previous post saying:
  foo x = map (bar x)
 should be rejected as ambiguous without a type signature somewhere

What type signature do you propose?

It seems as if you're proposing that 

  doubleSet :: Set.Set Int - Set.Set Int
  doubleSet = map (*2)

  doubleList :: [Int] - [Int]
  doubleList :: map (*2)

work, but that you not be allowed to notice that the definitions are
identical and substitute

  double = map (*2)

for both definitions.

Sorry, but I use Haskell specifically because I do *not* want to use C
++.

jcc


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Johannes Waldmann



As to the argument that a sufficiently smart IDE would insert the
M. for me, I think that is flawed.  First, there isn't a
sufficiently smart IDE yet, 


I do believe there will be.
What we do now is sort of putting down requirements ...


and second, it'd be better for the
type-aware IDE to tell me the types of things when I (for example)
mouse over them, instead of helping me type longer things.


That's been said before: an IDE might help in writing/changing code,
but code should be readable without tool support.

J.W.




signature.asc
Description: OpenPGP digital signature
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread David House
2008/8/31 Ryan Ingram [EMAIL PROTECTED]:
 My proposal is to allow ad-hoc overloading of names; if a name is
 ambiguous in a scope, attempt to type-check the expression against
 each name.  It is only an error if type-checking against all names
 fails.  If type-checking succeeds for more than one then the
 expression is ambiguous and this is also an error.

-1, at least for now.

Haskell already has one method of overloading: type classes. What you
propose is a seemingly innocent extension that I now doubt has
extremely far-reaching consequences into the language. Such a feature
should be properly researched before it is added to the language.
Here's an example of such a concern: you write the following:

import Data.Map
foo = map

What is the type of `foo'? I can think of several solutions to this
problem: one that springs to mind is to create something akin to an
on-the-fly typeclass class HasMap h where map :: h and add
instances for [a] and Ord k = Map k a. But I suspect there are other
options, with differing semantics. What if you further define bar =
map (+1), what happens then? Etc. etc.

The point I'm trying to make is that such a seemingly simple change is
in actual fact not nearly as simple as you might expect. So we should
consider carefully how this changes the language, and whether it's
worth it.

-- 
-David
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Philippa Cowderoy
Oops, forgot to send to list.

On Mon, 2008-09-01 at 01:27 +0100, Philippa Cowderoy wrote:
 On Mon, 2008-09-01 at 01:11 +0100, David House wrote:
  2008/8/31 Ryan Ingram [EMAIL PROTECTED]:
   My proposal is to allow ad-hoc overloading of names; if a name is
   ambiguous in a scope, attempt to type-check the expression against
   each name.  It is only an error if type-checking against all names
   fails.  If type-checking succeeds for more than one then the
   expression is ambiguous and this is also an error.
  
  -1, at least for now.
  
  Haskell already has one method of overloading: type classes. What you
  propose is a seemingly innocent extension that I now doubt has
  extremely far-reaching consequences into the language. Such a feature
  should be properly researched before it is added to the language.
  Here's an example of such a concern: you write the following:
  
  import Data.Map
  foo = map
  
  What is the type of `foo'?
 
 If I've understood the proposal, that wouldn't check unless foo was used
 in a way (within the module) that makes it clear which of Prelude.map or
 Data.Map.map to use and uses it consistently. So if that's the entire
 module, it wouldn't check.
 
 I'm still not keen, but in a sense the idea here is to avoid this
 variety of overloading leaking into the type system itself: it could be
 implemented (extremely naively) as typecheck with each possible
 permutation for resolving the overloading, use any unique solution or
 fail if there isn't one.

-- 
Philippa Cowderoy [EMAIL PROTECTED]

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Ryan Ingram
On Sun, Aug 31, 2008 at 4:21 PM, Jonathan Cast
[EMAIL PROTECTED] wrote:
 It seems as if you're proposing that

  doubleSet :: Set.Set Int - Set.Set Int
  doubleSet = map (*2)

  doubleList :: [Int] - [Int]
  doubleList :: map (*2)

 work, but that you not be allowed to notice that the definitions are
 identical and substitute

  double = map (*2)

 for both definitions.

Yes, that's exactly what I am suggesting.  This is especially
important because Set cannot be made an instance of Functor because of
the Ord restriction on the elements, so you can't generalize to fmap
without redefining Functor as RestrictedFunctor or some such, which
adds a ton of additional type-level programming that shouldn't be
required for day-to-day work.

I'm not against being able to use double = map (*2) generally, but
the evidence I've seen says that the PL theory isn't there yet to do
so without unacceptable performance penalties.  (That definition
violates the monomorphism restriction anyways).

 Sorry, but I use Haskell specifically because I do *not* want to use C++.

I don't think a language I dislike also has this feature is a good
argument against a feature.  C++ also has named fields in records, and
a standard I/O library.  Should Haskell not have those either?

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Ryan Ingram
On Sun, Aug 31, 2008 at 5:11 PM, David House [EMAIL PROTECTED] wrote:
 Here's an example of such a concern: you write the following:

 module Amb where
 import Data.Map

 foo = map

 What is the type of `foo'?

Exactly the same as now: it has no type:

amb.hs:4:6:
Ambiguous occurrence `map'
It could refer to either `Prelude.map', imported from Prelude
  or `Data.Map.map', imported from Data.Map at
amb.hs:2:0-14

On the other hand, this module would no longer fail to compile:

 module Amb where
 import Data.Map

 foo :: (a - b) - [a] - [b]
 foo = map

which right now gives the same error message as above, but with my
proposal would successfully compile, with foo = Prelude.map.

As Philippa said, the naive implementation is:

1) Attempt to typecheck with all permutations of ambiguous names
2a) If zero permutations typecheck, type error.
2b) If multiple permutations typecheck, the program is ambiguous
(current behavior)
2c) Otherwise, exactly one typechecks successfully.  Specialize the
ambiguous names to the chose permutation and continue compilation.

It is a conservative extension of the language, because any program
that successfully compiles now has no change: there are no ambiguous
names in any currently compiling Haskell program.  But it accepts some
additional programs that have ambiguities, by choosing the only result
that typechecks.  If there is more than one possible type for foo, the
program is still ambiguous and therefore should not compile.

  -- ryan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Marc Weber
On Sun, Aug 31, 2008 at 11:21:44AM -0700, Ryan Ingram wrote:
 [..]
 Any thoughts?
   -- ryan
Nice problem, nice idea..
Maybe the time is better spend on IDEs than extending the (or all)
compilers..

Right now I've something like this in my vim script files:

function! vl#dev#haskell#qffixfixable#AddMissingExtensions()
  let addExt=''
  let alreadyAsked = {}
  for qfitem in reverse(getqflist())
let match = matchstr(qfitem['text']
  \ , '(use -X\zs[^)]*\ze)\|(-X\zs[^ ]*\ze permits this)\|(Use \zs[^ ]*\ze 
to lift this restriction)'
  \  .'\|(Use -X\zs[^ ]*\ze to allow operators in types)'
  \  .'\|(Use -X\zs[^ ]*\ze to suppress this message)'
  \  .'\|Use -X\zs[^ ]*\ze if you want to disable this'
  \  .'\|Use -X\zs[^ ]*\ze to permit this'
  \  .'\|(Use -X\zs[^ ]*\ze to allow multi-parameter classes)'
  \  .'\|([Uu]se -X\zs[^ ]*\ze)'
  \  .'\|or use \zs[^ ]*\ze'
  \  .'\|(Use \zs[^ ]*\ze to permit this)'
  \  .'\|Use -X\zs[^ ]*\ze to permit it'
  \  .'\|Use -X\zs[^ ]*\ze if you want to allow more.)'
  \ )
let replace = {
\ '-fno-monomorphism-restriction'  : 'NoMonomorphismRestriction'
\ , '-fallow-undecidable-instances' : 'UndecidableInstances'
\ }
let match = get(replace, match, match)
if match != ''
  let addExt = match
endif
getting many information out of error message asking me wether I want to
add the used extension to the {#- LANGUAGE .. #-} pragma.

So what about enhancing ghc so that it prints a message such as

= hs  file ===
import qualified Data.Set as S
import qualified Data.Map as M
[..]

= error message ==
file.hs: line col: not in scope foo. Maybe you meant 
M.empty 
or S.empty

or without qualified

file.hs: line col: ambiguous occurence of empty, Maybe you meant
M.empty 
or S.empty

then it woulde be easy to ask the editor to do the right thing, give you
a choice ?

I'd say this is not as perfect as your proposal, but it can be
implemented much more easily.

Sincerly
Marc Weber
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] language proposal: ad-hoc overloading

2008-08-31 Thread Jonathan Cast
On Sun, 2008-08-31 at 19:06 -0700, Ryan Ingram wrote:
 On Sun, Aug 31, 2008 at 4:21 PM, Jonathan Cast
 [EMAIL PROTECTED] wrote:
  It seems as if you're proposing that
 
   doubleSet :: Set.Set Int - Set.Set Int
   doubleSet = map (*2)
 
   doubleList :: [Int] - [Int]
   doubleList :: map (*2)
 
  work, but that you not be allowed to notice that the definitions are
  identical and substitute
 
   double = map (*2)
 
  for both definitions.
 
 Yes, that's exactly what I am suggesting.  This is especially
 important because Set cannot be made an instance of Functor because of
 the Ord restriction on the elements, so you can't generalize to fmap
 without redefining Functor as RestrictedFunctor or some such, which
 adds a ton of additional type-level programming that shouldn't be
 required for day-to-day work.

This concept of `day-to-day work' is a curious one.  Haskell is not a
mature language, and probably shouldn't ever be one.  There will always
be new discoveries in purely functional programming, and as the art
advances, features like this ad-hoc overloading hack (and ACIO) will
become obsolete and have to be thrown over-board.  I'd rather (much
rather!) people concerned with day-to-day programming for writing
programs people actually use incorporate Haskell's features into other,
more practical, languages (as those who *actually* care about such
things are) rather than incorporating features from day-to-day
production languages into Haskell.

 I'm not against being able to use double = map (*2) generally, but
 the evidence I've seen says that the PL theory isn't there yet to do
 so without unacceptable performance penalties.

I don't believe in ``unacceptable performance penalties'' as a design
criterion for Haskell.  This is supposed to be a /research/ language.

 (That definition
 violates the monomorphism restriction anyways).

So?

  Sorry, but I use Haskell specifically because I do *not* want to use C++.
 
 I don't think a language I dislike also has this feature

How about ``a language I dislike specifically (among other things)
because of this `feature' also has this feature'?  The great problem
with C++ is that ad-hoc overloading allows operators to be defined in an
ad-hoc way.  In fact, C++ is now adding a feature similar to Haskell's
type classes, in an attempt to reign ad-hoc overloading in.  I don't
thing Haskell should be trying to unreign ad-hoc overloading instead.

  is a good
 argument against a feature.  C++ also has named fields in records, and
 a standard I/O library.  Should Haskell not have those either?

Standard I/O libraries are a bad idea, yes, and C++'s implementation of
named fields has the same problem --- lack of principle types --- as its
ad-hoc overloading.  So sure, I'd oppose Haskell introducing either.

jcc


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] ANN: vxml (validating xml lib) - maybe usable now, quadratic compilation time ?

2008-08-31 Thread Marc Weber
 There might still be some duplication.. in state transformation steps.
I've removed duplicate state machine paths.
Instead of approxmiately 1500 there are only 500 left.

You can see the impact on speed here
http://mawercer.de/~marc/vxml.svg
data  +  (red):  approx 1500
data3 *  (blue): approx 500 (current version)
data2 x (green): without validation

So most time is now spend somwhere else.

Sincerly
Marc Weber
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Top Level -

2008-08-31 Thread Ganesh Sittampalam

On Sun, 31 Aug 2008, Brandon S. Allbery KF8NH wrote:


On 2008 Aug 31, at 13:20, Ganesh Sittampalam wrote:


I'm afraid I don't see how this generalises to sharing something across an 
entire process where the things that want to do the sharing are not in or 
controlled by the same shared library. In particular the filehandle 
structures required for buffered I/O need to be common to every single 
piece of code in the process that might want to use them, no matter what 
language or language implementation that code uses.



For that you probably want to look at how ld.so.1 and libc interact to 
share the malloc pool and the stdin/stdout/stderr, among others.


If buffered IO is handled by libc rather than by specific language 
runtimes, then the same mechanism of using global variables inside libc 
would work fine; but this technique doesn't extend to providing 
process-scope shared state for library code that might be loaded multiple 
times with no knowledge of the other instances.


Ganesh
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe