Re: [Haskell-cafe] Current situation regarding global IORefs
Lennart Augustsson wrote: I think global mutable variables should be regarded with utmost suspicion. There are very few situations where they are the right solution. Well IMO even the use of the term global mutable variable causes muddled thinking on this and I wish people would stop it. There's no reason to regard top level things with identity (call them TWIs or objects or whatever) with any more suspicion than top level IO actions themselves. One thing I never could fathom about the position of the nay-sayers in this debate is what exactly is it that they object to? Is it existence of top level TWIs and of IO operations that reference them *in principle*? Or are they content with their existence but just don't want to allow people to use Haskell to define them? If it's the former then we should be purging the IO libraries of all such horrors, though I can't see much remaining of them (well anything actually). But I guess an IO incapable language might still have some niche uses. If it's the latter then we are advocating a language which cannot be used to implement many demonstrably useful IO modules and libraries, *by design*. If so, the claim that Haskell is a general purpose programming language seems quite bogus and should be removed from the haskell.org home page IMO. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Current situation regarding global IORefs
On 24/04/06, Adrian Hey [EMAIL PROTECTED] wrote: Lennart Augustsson wrote: I think global mutable variables should be regarded with utmost suspicion. There are very few situations where they are the right solution. Well IMO even the use of the term global mutable variable causes muddled thinking on this and I wish people would stop it. There's no reason to regard top level things with identity (call them TWIs or objects or whatever) with any more suspicion than top level IO actions themselves. What do you mean by top level IO action? If you mean something like 'getLine', then there is a huge difference. If you mean actions which execute automatically in any program which imports the given module, then I'd contend that Haskell doesn't really even have those (apart from possibly 'main', if you count that at all). In the latter case, you might have disconnected components which all must run, but since they do IO, are potentially noncommutative. With the ability to mark actions as automatically executing without some way to control the order of that execution, program behaviour is unpredictable in general. At least, I wouldn't want the language to allow that. However, putting an explicit ordering on their execution is essentially equivalent to defining a new IO action which executes each of them in a given sequence, obviating the need for such a feature in the first place. While only allowing the definition of top-level IORefs (i.e. not unrestricted IO) wouldn't cause quite as much harm, it's still questionable as to whether it's ever actually necessary. One can get computation-global IORefs easily using something along the lines of ReaderT IORef IO. By newtyping the monad, one could exert even more control over how the IORef was used. One problem with real top-level IORefs is that it leaves no way for the module user to reset things in general. As a library designer, you might think that the users of your library will only ever want to initialise things once, but this is being a little bit overly forceful -- what if the program has reloaded its configuration while running and wants to restart the functionality your module provides? If you haven't explicitly provided a way to reset the IORefs, there's no way for the module user to reliably do so. There are plenty of other nice ways to enforce things such as particular actions only running once and so on. For one, you could use a new monad, which would give extremely fine control over what actions were permitted, but even with just IO, there are plenty of things one can do -- just not globally. We can relatively easily create a context which provides an IO action that will only run once in that context, and return the same value as the first time without repeating the execution thereafter: singletonRegion :: IO a - (IO a - IO b) - IO b singletonRegion action region = do r - newIORef Nothing let action' = do t - readIORef r case t of Nothing - do v - action writeIORef r (Just v) return v Just v - return v region action' test1 = singletonRegion (putStrLn Hello) $ \greet - do greet -- only this one will actually have any effect. greet greet With a custom monad, this sort of setup would be built into the run function which transforms the action back into IO, and so would be even more transparent, while still not creating irrevocable program-global state. One thing I never could fathom about the position of the nay-sayers in this debate is what exactly is it that they object to? Is it existence of top level TWIs and of IO operations that reference them *in principle*? Or are they content with their existence but just don't want to allow people to use Haskell to define them? If it's the former then we should be purging the IO libraries of all such horrors, though I can't see much remaining of them (well anything actually). But I guess an IO incapable language might still have some niche uses. If it's the latter then we are advocating a language which cannot be used to implement many demonstrably useful IO modules and libraries, *by design*. If so, the claim that Haskell is a general purpose programming language seems quite bogus and should be removed from the haskell.org home page IMO. This argument sounds quite a lot like the ones used by those arguing against the removal of GOTO from programming languages. Sometimes, by explicitly not providing some feature, you're also making code in general easier to comprehend (especially when that feature has invisible global effects on programs, where you'd need to look carefully at the source of all modules involved in order to determine what was actually happening in the presence of its use). It can also prevent certain classes of design problems from ever cropping up. The more state which one has to reconstruct in order to test an arbitrary
[Haskell-cafe] Re: The case of the missing module
Neil Mitchell wrote: import Paths_haddock( getDataDir ) Haddock requires to be built with Cabal (which generates this module), and as far as I can remember, its a Cabal that isn't released anywhere. When I did some work on haddock I commented this out, and made getDataDir return an empty list and then made sure to set the -l flag (I think) and was able to work around this. Of course, the solution is to get Cabal working. I broke Cabal long ago, but you might have more luck. Haddock builds fine with the Cabal included in GHC 6.4.2, BTW. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: How to get Haddock to generate docs for a directory tree of modules
Brian Hulley wrote: I've been looking at the docs for Haddock at http://haskell.org/haddock/haddock-html-0.7/index.html but I can't seem to find any option to recursively traverse a directory generating hyperlinked docs for all modules anywhere in the directory or any sub directory etc. Is there a simple undocumented flag I'm missing? Haddock doesn't do this on its own, but Cabal can do it (./setup haddock). You do have to specify all the modules in the .cabal file though, so it's not really traversing a directory. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haddock seems to generate wrong types in newtype deriving
Brian Hulley wrote: Hi - I have the following code: data MState = MState -- details omitted type MonadStateMState = MonadState MState -- necessary for Haddock newtype ManagerM a = ManagerM (StateT MState IO a) deriving (Monad, MonadIO, MonadStateMState) which means that ManagerM is an instance of Monad, MonadIO, and MonadState MState. However, the Haddock docs look like: data ManagerM a Instances ??? a = Monad (ManagerM a) ??? a = MonadIO (ManagerM a) ??? a = MonadStateMState (ManagerM a) which doesn't seem at all right to me. I'd have thought it should say: data ManagerM a Instances Monad ManagerM MonadIO ManagerM MonadStateMState ManagerM Is this just a bug in Haddock or am I misunderstanding something about Haskell? It's a bug / missing feature in Haddock. Haddock is basically pretty dumb when it comes to understanding Haskell code; it knows about the syntax and the module system, and that's about all. It makes a half-hearted attempt to figure out what instances you get from deriving clauses, but it's not complete, and you've encountered a case it doesn't handle. One day Haddock will be built on top of the GHC API, and all this will be fixed... Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Advice needed on best way to simulate an STL vector
On Wed, Apr 19, 2006 at 09:32:19PM +0200, Udo Stenzel wrote: We don't have an implementation of Ropes (yet?). I think, a Finger Tree of Fast Packed Strings might be the closest thing. I'd even implement it this way, if the low performance of raw Strings finally overcame my inertia... Sounds like a good idea. I've placed the general annotated finger tree structure from our paper on the webpage http://www.soi.city.ac.uk/~ross/papers/FingerTree.html It might be useful if anyone would like to attempt this. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haddock seems to generate wrong types in newtype deriving
Simon Marlow wrote: Brian Hulley wrote: Hi - I have the following code: [snip] Is this just a bug in Haddock or am I misunderstanding something about Haskell? It's a bug / missing feature in Haddock. Haddock is basically pretty dumb when it comes to understanding Haskell code; it knows about the syntax and the module system, and that's about all. It makes a half-hearted attempt to figure out what instances you get from deriving clauses, but it's not complete, and you've encountered a case it doesn't handle. One day Haddock will be built on top of the GHC API, and all this will be fixed... Thanks - I'm glad it's not just me! In the meantime, I found a better workaround (since the type decl using a class name is not legal Haskell) is just to use -cpp to preprocess for both ghc and haddock so that haddock sees explicitly defined dummy instances instead of a newtype deriving clause, then perfect results are obtained... :-) Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: How to get Haddock to generate docs for a directory tree of modules
Simon Marlow wrote: Brian Hulley wrote: I've been looking at the docs for Haddock at http://haskell.org/haddock/haddock-html-0.7/index.html but I can't seem to find any option to recursively traverse a directory generating hyperlinked docs for all modules anywhere in the directory or any sub directory etc. Is there a simple undocumented flag I'm missing? Haddock doesn't do this on its own, but Cabal can do it (./setup haddock). You do have to specify all the modules in the .cabal file though, so it's not really traversing a directory. Thanks for this suggestion. I've also got things to work quite well by using the following makefile on a Windows command shell (using a Win32 port of gnu make and based on a helpful example makefile received offlist): # Makefile for Haddock docs GHCFLAGS = -fglasgow-exts -fffi API_FILES := $(wildcard *.hs) # preprocess for Haddock %.haddock:%.hs ghc $(GHCFLAGS) -cpp -E -optP-P -D__HADDOCK__ $^ -o docs/$@ # generate docs docs: $(patsubst %.hs,%.haddock,$(API_FILES)) haddock -o docs -h $(addprefix docs/, $^) This works as long as all the subdirectories containing modules are explicitly listed in API_FILES, and the whole directory tree (including the docs directory) is manually created (for Windows, since Windows doesn't automatically create directories that don't exist when it tries to open a file for writing when the filename contains a path) - not a big problem since the directory tree only needs to be created once. Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Current situation regarding global IORefs
Adrian Hey wrote: . I was going to respond, but Cale very eloquently said most of what I was thinking. Let me just add one thing. Sometimes you hear the argument I need a global IORef here because it's to track the use of my single screen (or keyboard, or elevator, or some some other gizmo in th real world). I think such decisions are just generally poor design, and it should not be done in any language. The number of physical resources that a program can control should never be assumed to be one; things change. -- Lennart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Control.Exceptions and MonadIO
Brian Hulley wrote: I've started work on a module to replace Control.Exception by wrapping all the original Control.Exception functions in more general monadic functions and using two type classes as follows: class MonadIO m = MonadException m where catch :: m a - (Exception - m a) - m a catchDyn :: Typeable exception = m a - (exception - m a) - m a catchJust :: (Exception - Maybe b) - m a - (b - m a) - m a try :: m a - m (Either Exception a) tryJust :: (Exception - Maybe b) - m a - m (Either b a) and class MonadIO m = MonadIOU m where getUnliftIO :: m (m a - IO a) All the other functions can be implemented just using MonadIO or MonadIOU or MonadException in place of IO (depending on the function eg bracket needs MonadIOU) - just in case anyone is interested. After more thought, it seems that it *should* be possible to implement block and unblock for StateT monads under certain conditions, using a different unlift function to return IO (a,s) instead of just IO a. Therefore I've changed things around, and also by looking at the source code for the current Control.Exception module, arrived at the following revised design (I've implemented all the other functions in terms of the classes below) class MonadIO m = MonadException m where catch :: m a - (Exception - m a) - m a catchDyn :: Typeable exception = m a - (exception - m a) - m a block, unblock :: MonadException m = m a - m a class MonadIO m = MonadIOU m where getUnliftIO :: m (m a - IO a) However I then want to say that any instance of MonadIOU is also an instance of MonadException. I tried: instance MonadIOU m = MonadException m where catch action e_m = do unliftIOa - getUnliftIO unliftIOb - getUnliftIO liftIO $ C.catch (unliftIOa action) (\e - unliftIOb(e_m e)) -- etc but this only compiles with -fallow-undecidable-instances. I'm puzzled at why there is a problem with such a simple instance declaration, and also don't know if this means my design is fatally flawed. The highlight of the above design is that all that's needed for many monads such as MonadIOU m = ReaderT r m is a definition of the one unlifting function, but it also allows instances of MonadException to be declared where the monad (eg a StateT s m) doesn't support this particular operation. Any ideas? Thanks, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Google Summer of Code 2006
Hello, Haskell.org is going to partecipate as mentoring organization to the Google Summer of Code programme of this year. We have formed a group of volunteers taking care of the administrative work as well as the mentoring part. The group is listed here: http://haskell.org/haskellwiki/Summer_of_Code:_People. We are now looking for projects, and mentors. We've reached number 24 but we are happily going to add more, Haskell Open Source paid work for the summer! If you run some active open source program you might want to mentor some student who will be working on your code, for example. Either just add your ideas here: http://haskell.org/haskellwiki/Summer_of_Code:_Project_suggestions (as well as your informations on the People's page) or contact me for details. I am also looking for students, I'd like to ear from them if they are going to partecipate with Haskell projects, last year I was alone! (I did write the bindings to the Cairo vector graphics library and integrated them in Gtk2Hs.) Details about the programme itself can be found on the official webpage: http://code.google.com/summerofcode.html Hoping you like the idea as much as me, Paolo. -- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Current situation regarding global IORefs
On Apr 24, 2006, at 2:42 AM, Adrian Hey wrote: Lennart Augustsson wrote: I think global mutable variables should be regarded with utmost suspicion. There are very few situations where they are the right solution. Well IMO even the use of the term global mutable variable causes muddled thinking on this and I wish people would stop it. There's no reason to regard top level things with identity (call them TWIs or objects or whatever) with any more suspicion than top level IO actions themselves. Sure there is. TWI's are just the object-oriented singleton pattern warmed over, and the singleton pattern is much maligned in some circles (for good reason, IMO). One thing I never could fathom about the position of the nay-sayers in this debate is what exactly is it that they object to? Is it existence of top level TWIs and of IO operations that reference them *in principle*? Or are they content with their existence but just don't want to allow people to use Haskell to define them? The former, in my case. As I stated in an earlier message, the problem is primarily one of defining the dynamic scope of the thing. If you look back in the archives, you'll notice I proposed a thread- local state mechanism because I felt it placed the scope boundary in an appropriate place, where it could be manipulated and reasoned about by programmers, and where it has a reasonable semantic interpretation. Presumably, runtime models will have to deal somehow with the notion of a thread of execution (even if just to say there is only ever one) and will thus fix the dynamic scope of thread local state. I additionally think that thread-local state (and similar mechanisms) can be abused to create difficult-to-maintain and buggy code, but that's a somewhat separate issue. If it's the former then we should be purging the IO libraries of all such horrors, though I can't see much remaining of them (well anything actually). But I guess an IO incapable language might still have some niche uses. Argument by straw-man: there are important differences between regular IO actions and TWI's, AKA singletons. The former is referentially transparent, while the latter is referentially opaque, for starters. There's also the scoping issue: the properties of the IO monad bound the dynamic scope of regular IO actions, but not so for singletons. If it's the latter then we are advocating a language which cannot be used to implement many demonstrably useful IO modules and libraries, *by design*. If so, the claim that Haskell is a general purpose programming language seems quite bogus and should be removed from the haskell.org home page IMO. You presuppose that a language which cannot be used to implement many demonstrably useful IO modules and libraries is not general purpose. I claim that is silly. If we take that argument to its logical conclusion, then we should throw out static typing, referential transparency and most of the things that make Haskell what it is. I think that what a programming language keeps you from doing is as least as important as what it lets you do. If you don't believe that at least to some extent, then your first exposure to Haskell probably made your head explode. That said, I also disagree with the premise. I don't know of any stateful library designs that can't be pretty straightforwardly refactored using explicit initialization and ReaderT-over-IO monads. Furthermore, I believe that a library so structured is actually _more_ useful than the library with implicit state. Regards -- Adrian Hey Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe