[ ghc-Bugs-681062 ] Confusing Error Message if package-name is omitted
Bugs item #681062, was opened at 2003-02-05 17:09 Message generated for change (Comment added) made by simonmar You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=681062group_id=8032 Category: Driver Group: None Status: Closed Resolution: Fixed Priority: 5 Submitted By: Wolfgang Thaller (wthaller) Assigned to: Nobody/Anonymous (nobody) Summary: Confusing Error Message if package-name is omitted Initial Comment: I compiled a library as a GHC package without adding the appropriate package-name flag to the ghc command line. When trying to compile a module that used the package, ghc complained that it couldn't find package quot;Mainquot;. This happens with the HEAD. With GHC 5.04 it (seemingly) was no problem to leave out the -package-name specifier. Why is the -package-name flag needed at all? -- Comment By: Simon Marlow (simonmar) Date: 2004-11-25 13:57 Message: Logged In: YES user_id=48280 -package-name will be gone in 6.4 (yay!), so I can close this bug. -- You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=681062group_id=8032 ___ Glasgow-haskell-bugs mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
[ ghc-Bugs-1073424 ] Segfault during (FFI)malloc with ghci
Bugs item #1073424, was opened at 2004-11-25 13:17 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=1073424group_id=8032 Category: None Group: 6.2.1 Status: Open Resolution: None Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: Segfault during (FFI)malloc with ghci Initial Comment: From: Tom Pledger [EMAIL PROTECTED] The attached program halts with a segmentation fault when run using ghci, but not when compiled with ghc and run natively Platform: Mandrake, linux kernel version 2.4.27-xena-1 -- You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=1073424group_id=8032 ___ Glasgow-haskell-bugs mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
[ ghc-Bugs-1073501 ] checkProddableBlock: invalid fixup in runtime linker
Bugs item #1073501, was opened at 2004-11-25 17:56 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=1073501group_id=8032 Category: None Group: 6.2.1 Status: Open Resolution: None Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: checkProddableBlock: invalid fixup in runtime linker Initial Comment: From: Tom Pledger [EMAIL PROTECTED] Platform: Mandrake, linux kernel version 2.4.27-xena-1 This one has a good workaround: leave off the -g flag when compiling C for use with ghci. $ echo int hello(){} hello.c $ gcc -g -c hello.c $ ghci hello.o ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.2.1, for Haskell 98. / /_\/ __ / /___| | http://www.haskell.org/ghc/ \/\/ /_/\/|_| Type :? for help. Loading package base ... linking ... done. Loading object (static) hello.o ... done final link ... ghc-6.2.1: internal error: checkProddableBlock: invalid fixup in runtime linker Please report this as a bug to glasgow-haskell- [EMAIL PROTECTED], or http://www.sourceforge.net/projects/ghc/ -- You can respond by visiting: https://sourceforge.net/tracker/?func=detailatid=108032aid=1073501group_id=8032 ___ Glasgow-haskell-bugs mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [Haskell] Real life examples
Ben Rudiak-Gould wrote: Lennart Augustsson wrote: What do you mean when you say the interface is pure? If your module is really pure then there should be an implemenation of it (which could have really bad complexity) with the same observable behaviour that uses only pure Haskell. Is this possible? Really? I agree with the converse of that statement, but I don't think it goes both ways. To me a function or module is pure when you can use it without compromising the equational properties of the language. I don't think Data.Dynamic or Control.Monad.ST satisfy your criterion for purity, but I would call them pure (after discarding the functions marked unsafe in the latter). Agreed, there can pure functions that cannot be written with the pure primitives, but then you have a proof obligation. An easy way to prove it is to provide an equivalent implementation that uses only pure functions. As far as I remember Control.Monad.ST can be written purely. And I think the same is true for Data.Dynamic. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
[EMAIL PROTECTED] wrote: G'day all. Quoting Lennart Augustsson [EMAIL PROTECTED]: Here is a small puzzle. You can understand this one because the closed world hypothesis doesn't apply to type context inference. I have no problem understanding the technical reason for this. But I now think it's a poor design. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
John Meacham wrote (snipped): George Russell's library is precicly an invalid use of unsafePerformIO. Internally, it does the invalid unsafePerformIO (newIORef) trick which is exactly the problem we are trying to solve. hiding it in a module doesn't make it go away. Why does it matter to you if it uses unsafePerformIO, so long as you are protected from all the unsafe consequences? Would you be happier if I required all values to instance (Read,Show) and then implemented exactly the same interface with this additional restriction using completely standard Haskell 98 by writing values to files and reading them back again? I am not positive, but it also would also add the overhead of a finitemap lookup across all global variables for every look up. which doesn't really meet efficiency requirements. a global counter should only need a single peek poke to a constant location, not some data structure lookup. Oh really, we're not arguing about efficiency at this stage of the game are we? Actually you could implement the whole thing with a single hash table. I would have done, if TypeRep and ThreadId exposed their internal integer contents for hashing purposes. ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
Lennart wrote (snipped): An easy way to prove it is to provide an equivalent implementation that uses only pure functions. As far as I remember Control.Monad.ST can be written purely. And I think the same is true for Data.Dynamic. I don't see how it can be, since you can use Data.Dynamic to provide an unsafe function cast : a - b newtype UnsafeCast a = UnsafeCast a instance Typeable (UnsafeCast a) where typeOf _ = mkAppTy (mkTyCon ) [] cast :: a - b cast a = let Just (UnsafeCast b) = fromDynamic (toDyn (UnsafeCast a)) in b ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
I don't necessarily agree that you can do this trick in all implementations of Dynamic and Typable. You're relying on more things than the interface to Dynamic promises. Your fromDynamic could very well return Nothing. And should! But that doesn't matter. The unsafeCast function doesn't really worry my much. It's unsafePerformIO that worries me. Using unsafe casts just makes us program in the untyped lambda calculus, where the beta rule still holds, so no worries. Whereas unsafePerformIO opens an entirely different can of worms. -- Lennart George Russell wrote: Lennart wrote (snipped): An easy way to prove it is to provide an equivalent implementation that uses only pure functions. As far as I remember Control.Monad.ST can be written purely. And I think the same is true for Data.Dynamic. I don't see how it can be, since you can use Data.Dynamic to provide an unsafe function cast : a - b newtype UnsafeCast a = UnsafeCast a instance Typeable (UnsafeCast a) where typeOf _ = mkAppTy (mkTyCon ) [] cast :: a - b cast a = let Just (UnsafeCast b) = fromDynamic (toDyn (UnsafeCast a)) in b ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
[Haskell] Re: Top-level -
On Thu, Nov 25, 2004 at 10:07:20AM +0100, George Russell wrote: John Meacham wrote: Now, my mdo proposal as written would have hello outputed exactly once at module start up time no matter what, whether x is demanded or not. it is equivalant to a program transformation that collects all the top level initializers and declarations, puts them all in a mdo block and runs it with the semantics explained in the fixIO paper. (with a deterministic, but partially undefined order) What happens if you write the following? y - f x - let f = something depending on x Will it know to evaluate x before y, or is this not allowed? What about if the assignments to y and x occur in different modules? Will the RTS have to analyse the dependencies to work out which order to run the assignments in?` No. The semantics are completly and precicely defined by the fixIO paper. there is a simple desugaring to haskell which I gave in my original proposal. The basic gist is that things occur almost* identically to if everything were simply placed in a single mdo block. no dependency analysis or strange translation beyond the normal haskell desugaring mechanisms is required. recursive top level declarations are no more tricky than are normal recursive lets. Yes it is possible to write divergent statements, in the same way it is possible to say bottom = bottom you can also say bottom' - return bottom' (these are actually equivalant.) Remember, that unlike normal monadic binding, this is using recursive monadic binding, meaning the results of future computations can be used as long as they arn't strictly evaluated, in the same way you can write mutually recursive variables but if both are strict in each other they will diverge :). The fact that everyone seems to get along fine despite the ability to write divergent computations with recursive lets makes me think this won't be too much for anyone to handle. John * The differences, which I elaborated on earlier are due to a monomorphic restriction on user-written 'mdo' let-bound variables which is irrelevant to the desugaring so the translation from mdo - haskell expression is slightly different than presented in the paper. -- John Meacham - repetae.netjohn ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
On Wednesday 24 Nov 2004 9:37 pm, John Meacham wrote: On Wed, Nov 24, 2004 at 03:48:56PM +, Keean Schupke wrote: Having admited to wavering on the edge of accepting top level TWIs, perhaps one of the supporters would like to comment on qualified importing... IE what happens to the unique property if I import 2 copies like so: module Main where import Library as L1 import Library as L2 Although each library's internal state is initialised once, as required, any real IO could lead to problems... With the device driver example I now have two bits of code that think they have exclusive access to the device... But I can do: Hmm? I am not really sure what you are asking. With my mdo proposal, and I think all proposals brought forth, the module system behaves identically to how it normally does for namespace control. top level initializers are just constant definitions for all most everything is concerned. modules do not change code at all, they are pure syntantic sugar for deciding what names you can see. i.e. it does not matter whether you do import List as L1 import List as L2 L1.sort and L2.sort refer to the same thing. it would be no different if sort were written with global state or even was a top level binding. I think Keean is assuming the idea is that one should be able to duplicate top level TWIs by importing the same module twice. But of course this is not what's wanted. For example, it would enable users to short circuit the safety provisons of all the oneShot examples. If the purpose of a module is to allow users to have multiple distinct (top level or otherwise) TWIs then it should be exporting an appropriate newTWI constructor which is used in the usual manner by the importing module(s).. myTWI - newTWI myOtherTWI - newTWI Regards -- Adrian Hey ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
[Haskell] Lexically scoped type variables
| This is a great example, thanks for posting it. However, I feel like | the real problem in this example is the lexically-scoped type | variables declared with your function f. Paul's message gives me an excuse to consult the Haskell list about the design of lexically scoped type variables. I have a two particular questions I'd like your advice about. (This is nothing to do with monomorphism restriction, or Lennart's original puzzle.) I'm sending this message to the main Haskell list, to maximise readership, but I suggest that you reply to [EMAIL PROTECTED] Thereby to avoid spamming the main Haskell list, which is meant to be low-bandwidth. I believe I've set the reply-to field of this message to achieve this goal. [Perhaps others can do the same?!] Simon Background First, for background you might want to glance at Lexically scoped type variables, an unpublished paper available at http://research.microsoft.com/%7Esimonpj/papers/scoped-tyvars I don't want to take time in this message to discuss why we want scoped type variables; I'll just take it for granted here. One design choice discussed in the paper, and implemented in GHC, is that we can bring new lexically-scoped type variables into scope by mentioning them in a pattern type signature: f (x::a) = Here 'a' is a name for the type of x, and 'a' scopes over f's body, and can be mentioned in type signatures in f's body. Sometimes one wants to name types in the result* of f, rather than it its *arguments*. For example head (xs::[a]) :: a = ... Here, the :: a before the = gives the type of head's result. If a result type signature binds a type variable, that type variable scopes over the right hand side of the definition. In GHC, it's not necessary for the type that 'a' names to be a type variable; it could be Int, for example: f (x::a) = x + (1::Int) Already this embodies several design choices. For example, we know that 'a' is a *binding* for 'a' because there is no 'a' already in scope, otherwise it'd be an *occurrence* of 'a'. (An alternative would be to mark binding sites somehow.) Also once could require that 'a' names a type variable rather than an arbitrary type. But for this message I want to take GHC's design as given. QUESTION 1 - In GHC at present, a separate type signature introduces no scoping. For example: f :: forall a. a - a f x = (x::a) would be rejected, because the type signature for 'f' does not make anything scope over the right-hand side, so (x::a) means (x::forall a.a), which is ill typed. An obvious alternative, taken up by (among others) Mondrian and Chamaeleon, is to say that the top-level quantified variables of a separate type signature scope over the right hand side of the binding In the above example, then, the 'a' bound by the 'forall' would scope over the right hand side of 'f'. I've argued against this in the past, because the construct (forall a. type) patently scopes 'a' only over type. But my resolve is weakening. It's just too convenient! Furthermore, it binds a *rigid* type variable (i.e. 'a' really must name a type variable) and that's important for GADTs... which strengthens the case. In short, I'm considering adopting the Mondrian/Chameleon rule for GHC. There are two variations 1a) In the example, 'a' is only brought into scope in the right hand side if there's an explicit 'forall' written by the programmer 1b) It's brought into scope even if the forall is implicit; e.g. f :: a - a f x = (x::a) I'm inclined to (1a). Coments? - QUESTION 2 -- Question 2 concerns degenerate bindings. First, consider pattern bindings. For example: let (x::[a], y) = rhs in body The LHS of the let-binding is a pair, so it's called a pattern binding. What should the scope of 'a' be? GHC's current story is that it is the same as the scope of term variables bound in the same pattern, so just as 'x' scopes over both rhs and body, so does 'a'. And that in turn means that we can't generalise over 'a', so 'x' is monomorphic. An alternative would be to say that type variables bound in a pattern binding scope only over the right-hand side. The degenerate case: variable bindings Now the nasty case let f :: a - a = \x - x in (f True, f 'c') Is the binding for 'f' (A) a (degenerate) function binding no arguments, but with a result signature? or (B) a (degenerate) pattern binding with pattern (var::type)? If we consider it to be (A) then arguably 'a' scopes only over the right-hand side, and f gets the polymorphic type (forall a. a- a). If we consider it to be (B) then currently 'a' scopes over the right hand side and the body of the let, so 'f' has to be monomorphic, with type ty-ty for some ty; and no ty will do, so the program is rejected. The trouble is that the
RE: [Haskell] Real life examples
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Marcin 'Qrczak' Kowalczyk Sent: den 25 november 2004 11:49 To: [EMAIL PROTECTED] Subject: Re: [Haskell] Real life examples Lennart Augustsson [EMAIL PROTECTED] writes: An easy way to prove it is to provide an equivalent implementation that uses only pure functions. As far as I remember Control.Monad.ST can be written purely. And I think the same is true for Data.Dynamic. I think neither of them can. I agree with Marcin. I challenge you (Lennart) to write Control.Monad.ST in Haskell98. I (and many others) have tried and failed. An interesting summary by Koen can be found here: http://www.haskell.org/pipermail/haskell/2001-September/007922.html Cheers, /Josef ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
No, with exactly the type signatures they have I don't think you can. But the untyped version of them can be implemented. And that is good enough to convince me that the beta rule is still valid. -- Lennart Josef Svenningsson wrote: -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Marcin 'Qrczak' Kowalczyk Sent: den 25 november 2004 11:49 To: [EMAIL PROTECTED] Subject: Re: [Haskell] Real life examples Lennart Augustsson [EMAIL PROTECTED] writes: An easy way to prove it is to provide an equivalent implementation that uses only pure functions. As far as I remember Control.Monad.ST can be written purely. And I think the same is true for Data.Dynamic. I think neither of them can. I agree with Marcin. I challenge you (Lennart) to write Control.Monad.ST in Haskell98. I (and many others) have tried and failed. An interesting summary by Koen can be found here: http://www.haskell.org/pipermail/haskell/2001-September/007922.html Cheers, /Josef ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Top Level TWI's again was Re: [Haskell] Re: Parameterized Show
On Wednesday 24 Nov 2004 11:50 am, Keean Schupke wrote: There is no problem getting multiple copies of the channels... I take it you are not familiar with the internals of OSs IME there is no uniformity wrt OS internals, and I can't claim to be familiar with them all. It's also fairly safe to assume that I know nothing about the internals of your OS. In any case, this is irrelevant to the scenario I originally posited. Remember I wrote: What if there is no OS or device driver? ---^ I.E. A typicial embedded environment (though it's common to use OSs here too, but the main reason for that is inadequacy of C). So all you have to work with is one complete, type safe, Haskell program, and the metal. In this scenario the only initialisation that's done prior to running main is initialisation of the Haskell rts. That said, the approach you outline below is workable and AFAICS immune to the problems I was talking about. But you've introduced an artificial distinction between OS and application to do this and as a result.. * Made comms between application and hardware really awkward IMO * Sacrificed type safety in these comms I think. (I have written a small OS myself, complete with real device drivers)... The OS is started at boot, it initialises its own state, then it forks the device drivers, then it forks user processes (simplified but adequate). Lets design a small Haskell OS, the OS has the handles for the device driver. The program MUST be passed the channels to the OS (there is no other way)... These channels allow other channels to be opened, they would be like the master device. main :: Chan CMD - Chan RSP - IO () main cmd rsp = do writeChan cmd (OpenDevice devname) h - readChan rsp case h of (OpenOK in out) - do writeCan out (DeviceWriteString hello) status - readChan in _ - error could not open device Here you can see that we could try and open the device again, however the OS would either multiplex or serialize the device depending on type. So you've gone for the third approach I identified, but with a slight variation. You've wrapped all the separate device drivers into a single uber device driver (world driver?) and called it the operating system. I think this approach has it's pros and cons, but you're right that it does solve the problem. But my original monosyllabic summary of MHO re. this approach still applies I'm afraid. Regards -- Adrian Hey ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
I have already asked Simon PJ if this can be implemented in GHC... So if more people ask for it, it might get done! Keean Lennart Augustsson wrote: Here is a small puzzle. -- The following generates a type error: f :: Char - Char f c = let x = g c in h x -- But this definition does not: f :: Char - Char f c = let x :: Bool x = g c in h x Furthermore, replacing Bool by any other type in the latter definition will always give a type error. How is this possible? Scroll down for the answer. Here is the module: module Puzzle(f) where f :: Char - Char f c = let x = g c in h x class C a where g :: Char - a h :: a - Char instance C Bool where g c = c == 'T' h b = if b then 'T' else 'F' The error message from ghc is Puzzle.hs:5:12: Ambiguous type variable `a' in the top-level constraint: `C a' arising from use of `g' at Puzzle.hs:5:12 I know the technical reason why this is happening. But it's hard for me to motivate why this is reasonable. The type variable `a' is not ambiguous at all, the only type it can possibly have is Bool; any other type is an error. Furthermore, there can never be any other instance of the class C added to any program using the module Puzzle since the class C is not exported. So in what sense is this really ambiguous? I think it would be quite reasonable to allow the Puzzle module to compile, resolving `a' to be Bool. I.e., if there is only one instance that can satisfy a constraint and there is no possibility of adding instances outside the compiled module, I think resolving the overloading makes sense. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
No, closed classes are different, here we are talking about lazy overlap resolution, so if at _call_ time only one instance fits we choose it. Closing a class is different. Keean. Daan Leijen wrote: Lennart Augustsson wrote: [snip] So in what sense is this really ambiguous? I think it would be quite reasonable to allow the Puzzle module to compile, resolving `a' to be Bool. I.e., if there is only one instance that can satisfy a constraint and there is no possibility of adding instances outside the compiled module, I think resolving the overloading makes sense. You may be interested in a recent paper by Bastiaan Heeren and Juriaan Hage [1] about type class directives. The closed directive in that paper is more or less implied by your example. Here is a quote from the paper: The main advantage of a closed type class is that we know the fixed set of instances. Using this knowledge, we can influence the type inference process. As discussed in the introduction to Section 2, we can reject definitions early on (in case the set of instances for a certain type class is empty) or improve a type variable to a certain type (in case the set of instances is a singleton). All the best, -- Daan Leijen. [1] http://www.cs.uu.nl/~bastiaan/papers.html#typeclassdirectives (to appear in PADL 2005) -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Keean Schupke wrote: No, closed classes are different, here we are talking about lazy overlap resolution, so if at _call_ time only one instance fits we choose it. Closing a class is different. A closed class directive however is an explicit specification that makes the intention of the designer explicit in the program. Since it would solve the puzzle in a rather elegant and explicit way, I thought that it was interesting to mention. All the best, -- Daan. Keean. Daan Leijen wrote: Lennart Augustsson wrote: [snip] So in what sense is this really ambiguous? I think it would be quite reasonable to allow the Puzzle module to compile, resolving `a' to be Bool. I.e., if there is only one instance that can satisfy a constraint and there is no possibility of adding instances outside the compiled module, I think resolving the overloading makes sense. You may be interested in a recent paper by Bastiaan Heeren and Juriaan Hage [1] about type class directives. The closed directive in that paper is more or less implied by your example. Here is a quote from the paper: The main advantage of a closed type class is that we know the fixed set of instances. Using this knowledge, we can influence the type inference process. As discussed in the introduction to Section 2, we can reject definitions early on (in case the set of instances for a certain type class is empty) or improve a type variable to a certain type (in case the set of instances is a singleton). All the best, -- Daan Leijen. [1] http://www.cs.uu.nl/~bastiaan/papers.html#typeclassdirectives (to appear in PADL 2005) -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
I have a concern with this, if I understand the issue correctly. Suppose I have a source module that compiles and runs correctly. Now suppose I add a restricted (selective) import statement to the file, explicitly introducing a name that I know does not clash with anything in my module. I expect the module to continue to compile and run correctly. If I understand Lennart's proposal correctly, adding such an import could cause the compilation to fail, by adding new instance options that then needs to be disambiguated. Under the present regime, this is not a problem, because information to disambiguate the instance selection needs to added even if there's only one visible instance, so adding the restricted import cannot introduce this failure. Similar concerns might apply if new instances are added to a module that is already a restricted import. I suspect that the proper fix to this is that a selective import should also name the instances that are imported. Then disambiguation of instances can reasonably be based on just the visible imports. The automatic import of instances, even when the restricted form of import is used, has often seemed a little odd to me. #g -- At 14:36 25/11/04 +, Keean Schupke wrote: I have already asked Simon PJ if this can be implemented in GHC... So if more people ask for it, it might get done! Keean Lennart Augustsson wrote: Here is a small puzzle. -- The following generates a type error: f :: Char - Char f c = let x = g c in h x -- But this definition does not: f :: Char - Char f c = let x :: Bool x = g c in h x Furthermore, replacing Bool by any other type in the latter definition will always give a type error. How is this possible? Scroll down for the answer. Here is the module: module Puzzle(f) where f :: Char - Char f c = let x = g c in h x class C a where g :: Char - a h :: a - Char instance C Bool where g c = c == 'T' h b = if b then 'T' else 'F' The error message from ghc is Puzzle.hs:5:12: Ambiguous type variable `a' in the top-level constraint: `C a' arising from use of `g' at Puzzle.hs:5:12 I know the technical reason why this is happening. But it's hard for me to motivate why this is reasonable. The type variable `a' is not ambiguous at all, the only type it can possibly have is Bool; any other type is an error. Furthermore, there can never be any other instance of the class C added to any program using the module Puzzle since the class C is not exported. So in what sense is this really ambiguous? I think it would be quite reasonable to allow the Puzzle module to compile, resolving `a' to be Bool. I.e., if there is only one instance that can satisfy a constraint and there is no possibility of adding instances outside the compiled module, I think resolving the overloading makes sense. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
Thanks Adrian, for some reason I did not get the original reply to this post. This was my point, I may _want_ two copies of the library. Lets say I want to write a virtual machine emulator in haskell, and I then wish to use your library to drive the virtualised hardware... There must be some way to encapsulate the state requirement of the library such that the VM software can manage multiple states. At the momemt (with the handle approach) this is entirely possible: a - initLibrary b - initLibrary With you suggestion this VM cannot be written in Haskell any more. This is the point that I object to (and have been trying to explain badly). Perhaps the following extension would fix things: main = do a - import Library -- a would be a record containing top level of library b - import Library Keean. Adrian Hey wrote: On Wednesday 24 Nov 2004 9:37 pm, John Meacham wrote: On Wed, Nov 24, 2004 at 03:48:56PM +, Keean Schupke wrote: Having admited to wavering on the edge of accepting top level TWIs, perhaps one of the supporters would like to comment on qualified importing... IE what happens to the unique property if I import 2 copies like so: module Main where import Library as L1 import Library as L2 Although each library's internal state is initialised once, as required, any real IO could lead to problems... With the device driver example I now have two bits of code that think they have exclusive access to the device... But I can do: Hmm? I am not really sure what you are asking. With my mdo proposal, and I think all proposals brought forth, the module system behaves identically to how it normally does for namespace control. top level initializers are just constant definitions for all most everything is concerned. modules do not change code at all, they are pure syntantic sugar for deciding what names you can see. i.e. it does not matter whether you do import List as L1 import List as L2 L1.sort and L2.sort refer to the same thing. it would be no different if sort were written with global state or even was a top level binding. I think Keean is assuming the idea is that one should be able to duplicate top level TWIs by importing the same module twice. But of course this is not what's wanted. For example, it would enable users to short circuit the safety provisons of all the oneShot examples. If the purpose of a module is to allow users to have multiple distinct (top level or otherwise) TWIs then it should be exporting an appropriate newTWI constructor which is used in the usual manner by the importing module(s).. myTWI - newTWI myOtherTWI - newTWI Regards -- Adrian Hey ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Real life examples
John Meacham wrote: I should say that efficiency is the only thing I have been concerned about in this conversation. As I said in the mdo proposal, there is no efficient and safe way to do global variables in haskell. I think George Russell's library (with a simple extension) can be used to create global variables safely and with the same per-access efficiency as the other proposals: http://www.mail-archive.com/haskell@haskell.org/msg15709.html Your library addresses a different issue, it provides an interface for global variables, but it doesn't address the fundamental problem that your library or ones like it cannot be implemented in haskell. [...much elaboration on this idea omitted...] I think I completely answered this objection in another message yesterday: http://www.mail-archive.com/haskell@haskell.org/msg15723.html In short, his proposal should be considered in the same light as yours, as a /primitive/ extension to Haskell. (But I'd prefer you respond to my previous message rather than that sentence.) -- Ben ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Daan Leijen wrote: Keean Schupke wrote: No, closed classes are different, here we are talking about lazy overlap resolution, so if at _call_ time only one instance fits we choose it. Closing a class is different. A closed class directive however is an explicit specification that makes the intention of the designer explicit in the program. Since it would solve the puzzle in a rather elegant and explicit way, I thought that it was interesting to mention. Indeed, a closed directive would have been fine. But it's not really necessary, the class is obviously closed because of not being exported. But the type checker doesn't use this fact. I find it somewhat anomalous that there is one unique way to give types to my program, but that the type checker refuses to do it. :) -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Of course it can. I might do it myself. :) -- Lennart Keean Schupke wrote: I have already asked Simon PJ if this can be implemented in GHC... So if more people ask for it, it might get done! Keean Lennart Augustsson wrote: Here is a small puzzle. -- The following generates a type error: f :: Char - Char f c = let x = g c in h x -- But this definition does not: f :: Char - Char f c = let x :: Bool x = g c in h x ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Graham Klyne wrote: I have a concern with this, if I understand the issue correctly. Suppose I have a source module that compiles and runs correctly. Now suppose I add a restricted (selective) import statement to the file, explicitly introducing a name that I know does not clash with anything in my module. I expect the module to continue to compile and run correctly. If I understand Lennart's proposal correctly, adding such an import could cause the compilation to fail, by adding new instance options that then needs to be disambiguated. Not in my particular case. The class is local to the module. Any instance declaration would have to be in that module. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Better Exception Handling
John Goerzen wrote: So why do we have: catchJust :: (Exception - Maybe b) - IO a - (b - IO a) - IO a instead of: catchJust :: (Exception - Maybe b) - (c - a) - c - (b - a) - a As I'm sure you have gathered from all the answers you can't have the latter and keep Haskell pure. But there is an interesting alternative (at least theoretically). You could have a function like mkCatchJust :: IO ((Exception - Maybe b) - (c - a) - c - (b - a) - a) And you would use it by do cj - mkCatchJust cj The cj function can be used in non-IO code and will behave just as you want. But you have to create it in the IO monad, since it's behaviour is not deterministic (especially not in the face of async exceptions). The tricky thing is to implement it, because cj should really only be used once. Why? Because it has to behave the same way for the same arguments every time. This is not easily implemented. :( -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Better Exception Handling
On Thu, Nov 25, 2004 at 07:52:43PM +0100, Lennart Augustsson wrote: As I'm sure you have gathered from all the answers you can't have the latter and keep Haskell pure. But there is an interesting alternative (at least theoretically). You could have a function like mkCatchJust :: IO ((Exception - Maybe b) - (c - a) - c - (b - a) - a) How is that different from this? mkReadFile :: IO (FilePath - String) This is wrong. Even if I get a function as a result of an IO computation, I expect that function to be pure. The cj function can be used in non-IO code and will behave just as you want. But you have to create it in the IO monad, since it's behaviour is not deterministic (especially not in the face of async exceptions). IO monad shouldn't be used to create non-deterministic functions. The whole point in using IO monad is that functions stay pure, regardless of their origin. Best regards, Tomasz ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Better Exception Handling
On 25 Nov 2004, at 19:24, Tomasz Zielonka wrote: On Thu, Nov 25, 2004 at 07:52:43PM +0100, Lennart Augustsson wrote: As I'm sure you have gathered from all the answers you can't have the latter and keep Haskell pure. But there is an interesting alternative (at least theoretically). You could have a function like mkCatchJust :: IO ((Exception - Maybe b) - (c - a) - c - (b - a) - a) How is that different from this? mkReadFile :: IO (FilePath - String) This is wrong. Even if I get a function as a result of an IO computation, I expect that function to be pure. Well, you can presumably give it a semantics which is pure. Whether it makes good sense is another question. The semantics is 'it creates a function which, when invoked, will return the contents of the file at some fixed (undefined) time'. By the same token, you can just stick the function strangeReadFile :: FilePath - String into the language. As long as it is memoized, always returning the same value, it doesn't break beta-reduction. I call it 'strange' because the time that the file is actually read is not guaranteed, so if you read more than one file in your program, you have no guarantee that you are reading a constant total state that actually existed at any point in time. (Before you think this sounds unbearably horrible, there is at least one commercially sold RDBMS which has this semantics on its select statements ;P) Jules ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Better Exception Handling
Tomasz Zielonka wrote: On Thu, Nov 25, 2004 at 07:52:43PM +0100, Lennart Augustsson wrote: As I'm sure you have gathered from all the answers you can't have the latter and keep Haskell pure. But there is an interesting alternative (at least theoretically). You could have a function like mkCatchJust :: IO ((Exception - Maybe b) - (c - a) - c - (b - a) - a) How is that different from this? mkReadFile :: IO (FilePath - String) This is wrong. Why is this wrong? Even if I get a function as a result of an IO computation, I expect that function to be pure. Yes, so do I. The function returned will have to be pure. Pure in the sense that given the same argument it always has to return the same result. In the case of mkReadFile this is not too hard to implement. I admit that it is rather awkward, but it can be pure. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] Better Exception Handling
Jules Bean wrote: By the same token, you can just stick the function strangeReadFile :: FilePath - String into the language. As long as it is memoized, always returning the same value, it doesn't break beta-reduction. I call it 'strange' because the time that the file is actually read is not guaranteed, so if you read more than one file in your program, you have no guarantee that you are reading a constant total state that actually existed at any point in time. (Before you think this sounds unbearably horrible, there is at least one commercially sold RDBMS which has this semantics on its select statements ;P) It is also strange by the fact that strangeReadFile can very well be different functions at different runs of the program. That's why I think such a function should be generated by the IO monad. (If you want it at all!) -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Lennart Augustsson wrote: Daan Leijen wrote: A closed class directive however is an explicit specification that makes the intention of the designer explicit in the program. Since it would solve the puzzle in a rather elegant and explicit way, I thought that it was interesting to mention. Indeed, a closed directive would have been fine. But it's not really necessary, the class is obviously closed because of not being exported. But the type checker doesn't use this fact. I find it somewhat anomalous that there is one unique way to give types to my program, but that the type checker refuses to do it. :) You are right, I feel like that too: one should expect that the type checker can figure this out, and perhaps it is even really useful. On the other hand, suppose you decide later to export the class, and suddenly your code would no longer type check. The fact that adding an export defintion would lead to a type error somewhere else in the code might be rather confusing. (worse! it might be considered inelegant :-) Personally, I feel that this problem might be better solved by making a lot of the implicit assumptions (and semantics) of type classes more explicit, and bring them under user control. Of course, I do have not have any idea of how this should be done concretely ;-) (although type class directives might be a step in the right direction?) -- Daan ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Daan Leijen wrote: You are right, I feel like that too: one should expect that the type checker can figure this out, and perhaps it is even really useful. On the other hand, suppose you decide later to export the class, and suddenly your code would no longer type check. The fact that adding an export defintion would lead to a type error somewhere else in the code might be rather confusing. (worse! it might be considered inelegant :-) Yes, that is somewhat strange, I agree. :) Personally, I feel that this problem might be better solved by making a lot of the implicit assumptions (and semantics) of type classes more explicit, and bring them under user control. Of course, I do have not have any idea of how this should be done concretely ;-) (although type class directives might be a step in the right direction?) Yes, I think the type class directives is a step forwards. :) -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Daan Leijen wrote: You are right, I feel like that too: one should expect that the type checker can figure this out, and perhaps it is even really useful. On the other hand, suppose you decide later to export the class, and suddenly your code would no longer type check. I must have missed a mail... how could adding an export change the code? The fact that adding an export defintion would lead to a type error somewhere else in the code might be rather confusing. (worse! it might be considered inelegant :-) Keean. ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: [Haskell] A puzzle and an annoying feature
Keean Schupke wrote: Daan Leijen wrote: You are right, I feel like that too: one should expect that the type checker can figure this out, and perhaps it is even really useful. On the other hand, suppose you decide later to export the class, and suddenly your code would no longer type check. I must have missed a mail... how could adding an export change the code? If you export the class you can add another instance to it. And now my type variable would really be ambiguous. -- Lennart ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
[Haskell] Haskell-mode 2.0
I have recently taken over maintainership of Haskell-mode, and after making a bunch of changes, I figured it would be a good idea to make a new release. You can find this new release at: http://www-perso.iro.umontreal.ca/~monnier/elisp/ If you think it should also be found at http://www.haskell.org/haskell-mode/, then please tell John Peterson to get back to me (my email to him seem to go straight to the bitbucket. John?). This release has several changes that have all been only lightly tested, especially w.r.t compatibility with various Emacsen. See appended the NEWS file that describes some of the notewirthy changes. Stefan Changes since 1.45: * keybindings C-c char have been replaced by C-c C-char so as not to collide with minor modes. * The following modules are now automatically activated without having to add anything to haskell-mode-hook: haskell-font-lock (just turn on global-font-lock-mode). haskell-decl-scan (just bind `imenu' to some key). * In recent Emacsen, haskell-doc hooks into eldoc-mode. * haskell-hugs and haskell-ghci are superceded by inf-haskell. * Indentation rules have been improved when using layout inside parens/braces. * Symbols like - and \ can be displayed as actual arrows and lambdas. See haskell-font-lock-symbols. * Tweaks to the font-lock settings. Among other things paren-matching with things like \(x,y) should work correctly now. * New maintainer [EMAIL PROTECTED]. ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
[Haskell] Re: Top-level -
John Meacham wrote (snipped): recursive top level declarations are no more tricky than are normal recursive lets. Perhaps I am missing something, but surely one very important problem with - at top level is that calling for the value of something defined by - causes the corresponding action to be performed? Unless the actions available are very tightly restricted, this means that for example the meaning of a program depends on what order arguments to a pure functions are evaluated, for example. ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Low-level notation for type classes WAS: [Haskell] A puzzle and an annoying feature
Hi, Daan said: Personally, I feel that this problem might be better solved by making a lot of the implicit assumptions (and semantics) of type classes more explicit, and bring them under user control. Of course, I do have not have any idea of how this should be done concretely ;-) (although type class directives might be a step in the right direction?) Well, you might not need to look that far :) To a great extent you can use Constraint Handling Rules (CHRs) to explain type classes. E.g., consider Gregory J. Duck, Simon Peyton-Jones, Peter J. Stuckey and Martin Sulzmann Sound and Decidable Type Inference for Functional Dependencies Peter J. Stuckey and Martin Sulzmann A Theory of Overloading I've just skimmed through the Type Class Directives paper. Pl correct me if I'm wrong but it appears that the disjoint directive can be modeled by CHRs. Example: disjoint (Integral, Fractional) can be encoded by rule Integral a, Fractional a == False (1) The never directive is in fact a special instance of disjoint. E.g., never Num Bool can be encoded by rule Num Bool == False (2) Note that the Chameleon type debugger provides type error explanation support if the error is due to rule applications such as (1) and (2). Martin ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
[Haskell-cafe] [Haskell] Re: Global Variables and IO initializers
This is funny. When I got no immediate reaction from you, I started implementing it myself. I ended up with something similar. It has less features but is also a lot simpler. This is the interface: initGlobal :: Typeable a = a - IO () getGlobal :: Typeable a = IO a Your implementation is probably much simpler than mine because you don't implement withEmptyDict. I'm really quite keen about withEmptyDict, because one of the MAJOR conceptual problems I have with unsafePerformIO global variables is that you only get one universe, corresponding to the Haskell program. There shouldn't really be a single the Haskell program anyway; imagine something like GHC or an operating system written in Haskell which run sub-systems which require their own global variables. Or imagine a program split between lots of processors where, for efficiency reasons, you don't want everyone to have to refer to the same set of global variables.o Storing (TypeRep,Dynamic) pairs is redundant, since Dynamics already contain their own TypeRep (that is how they are made to work). It is, but I'm not sure if it can be avoided without using stuff not in the standard libraries. I also use a list for the dictionary; and I share your view about TypeRep badly needing an Ord instance (probably trivial to provide but I could be wrong). Even better would be a hashable integer. TypeRep actually is implemented internally on GHC using a hashcons'd unique integer, so exposing it should be trivial ... ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] RE: [Haskell] Lexically scoped type variables
Let me just begin by sharing my experience with scoped type variables. I've found them very useful in a project were I was to generalize a substantial code base. Many of the functions had local definitions whose type were simply not expressible without scoped type variables. During this work I found an interesting interplay between multi parameter type classes and scoped type variables. An example would look something like this: f :: C a b c = a - b f a = let g = ... The important thing to note is that the type variable c in f's signature occurs neither in the argument nor the result type of f. Hence c is not bindable by lexically scoped type variables. But suppose c is part of g's type. Then we still have no way of expressing g's type! This thing has bitten me and so I welcome the change you're planning. As for your questions I would prefer 1b although I don't think it is a big deal. For your second question I would go for 2c (which you've called 2b :). That's because I don't use result type signatures. Other people will surely disagree. Cheers, /Josef -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Simon Peyton-Jones Sent: den 25 november 2004 11:44 To: [EMAIL PROTECTED] Subject: [Haskell] Lexically scoped type variables | This is a great example, thanks for posting it. However, I feel like | the real problem in this example is the lexically-scoped type | variables declared with your function f. Paul's message gives me an excuse to consult the Haskell list about the design of lexically scoped type variables. I have a two particular questions I'd like your advice about. (This is nothing to do with monomorphism restriction, or Lennart's original puzzle.) I'm sending this message to the main Haskell list, to maximise readership, but I suggest that you reply to [EMAIL PROTECTED] Thereby to avoid spamming the main Haskell list, which is meant to be low-bandwidth. I believe I've set the reply-to field of this message to achieve this goal. [Perhaps others can do the same?!] Simon Background First, for background you might want to glance at Lexically scoped type variables, an unpublished paper available at http://research.microsoft.com/%7Esimonpj/papers/scoped-tyvars I don't want to take time in this message to discuss why we want scoped type variables; I'll just take it for granted here. One design choice discussed in the paper, and implemented in GHC, is that we can bring new lexically-scoped type variables into scope by mentioning them in a pattern type signature: f (x::a) = Here 'a' is a name for the type of x, and 'a' scopes over f's body, and can be mentioned in type signatures in f's body. Sometimes one wants to name types in the result* of f, rather than it its *arguments*. For example head (xs::[a]) :: a = ... Here, the :: a before the = gives the type of head's result. If a result type signature binds a type variable, that type variable scopes over the right hand side of the definition. In GHC, it's not necessary for the type that 'a' names to be a type variable; it could be Int, for example: f (x::a) = x + (1::Int) Already this embodies several design choices. For example, we know that 'a' is a *binding* for 'a' because there is no 'a' already in scope, otherwise it'd be an *occurrence* of 'a'. (An alternative would be to mark binding sites somehow.) Also once could require that 'a' names a type variable rather than an arbitrary type. But for this message I want to take GHC's design as given. QUESTION 1 - In GHC at present, a separate type signature introduces no scoping. For example: f :: forall a. a - a f x = (x::a) would be rejected, because the type signature for 'f' does not make anything scope over the right-hand side, so (x::a) means (x::forall a.a), which is ill typed. An obvious alternative, taken up by (among others) Mondrian and Chamaeleon, is to say that the top-level quantified variables of a separate type signature scope over the right hand side of the binding In the above example, then, the 'a' bound by the 'forall' would scope over the right hand side of 'f'. I've argued against this in the past, because the construct (forall a. type) patently scopes 'a' only over type. But my resolve is weakening. It's just too convenient! Furthermore, it binds a *rigid* type variable (i.e. 'a' really must name a type variable) and that's important for GADTs... which strengthens the case. In short, I'm considering adopting the Mondrian/Chameleon rule for GHC. There are two variations 1a) In the example, 'a' is only brought into scope in the right hand side if there's an explicit 'forall' written by the programmer 1b) It's brought into scope even if the forall is implicit; e.g. f :: a - a f x =
Re: [Haskell-cafe] [Haskell] Re: Global Variables and IO initializers
George Russell [EMAIL PROTECTED] writes: Your implementation is probably much simpler than mine because you don't implement withEmptyDict. I'm really quite keen about withEmptyDict, because one of the MAJOR conceptual problems I have with unsafePerformIO global variables is that you only get one universe, corresponding to the Haskell program. I think global variables are a lot less evil if they behave as if they were dynamically scoped, like Lisp special variables. That is, there is a construct which gives the variable a new mutable binding visible in the given IO action. It's used more often than assignment. Assignment is still available though. In Common Lisp implementations these variables are not inherited by threads: each thread starts with toplevel bindings of dynamic variables. I think this is wrong and they should be inherited. In my language Kogut they are inherited. With threads it makes a difference that the variable gets a new binding, not just a new value. The old binding is still mutable by threads which have not shadowed it. When the scope of the new binding finishes, the value restored in this thread might be different than the value from the time the scope was entered, if other threads have changed it in the meantime. In Haskell it would be a new kind of reference, parallel to IORef and MVar. In principle dynamic variables need not to be defined at the toplevel. In Lisp they are effectively always toplevel variables (even if declared locally); in my language they can be created in arbitrary places, e.g. as fields of objects. But usually they are toplevel. It would be pointless to *not* have toplevel dynamic variables, because their purpose is to avoid manually threading them through all actions which need them. This is an alternative design to Haskell's implicit parameters. It's different in that it applies to the IO monad only (dynamic variables obviously can't be read from pure code) and that the fact that an action uses a particular variable is not reflected in its type. Their primary use is to provide a default setting used in deep places in a computation, with the assumption that usually a single setting applies to the whole computation started from a given place. Like the random number generator, the default output handle (not the *internals* of stdOut as a statefulobject, but binding the stdOut variable to different handles, not possible in Haskell), the current locale or individual settings implied by the locale (I don't know yet how inheritable settings should be designed, like the locale as a whole and its parts). -- __( Marcin Kowalczyk \__/ [EMAIL PROTECTED] ^^ http://qrnik.knm.org.pl/~qrczak/ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Yet another IO initializer: Effectful declarations and an ACIO monad
On 25 Nov 2004, at 10:07, [EMAIL PROTECTED] wrote: Way back in this thread, Koen Claessen mentioned the idea of a commutative version of the IO monad for handling things with identity. That doesn't quite do it, but I have a refinement that might. The thing is to focus on IO computations that are: a) central -- their effect commutes with every other IO action b) affine -- their effect is not directly observable, and can be discarded. Thus an element u of (IO a) is affine central if for all v::IO b and w::IO c, do { x - u; v } = v(affine) If x does not occur in v, I presume? Jules ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Yet another IO initializer: Effectful declarations and an ACIO monad
On Thu, 25 Nov 2004, Jules Bean wrote: On 25 Nov 2004, at 10:07, [EMAIL PROTECTED] wrote: Thus an element u of (IO a) is affine central if for all v::IO b and w::IO c, do { x - u; v } = v(affine) If x does not occur in v, I presume? Yes, and similarly for centrality: do { x - u; y -v; w } = do { y - v; x - u; w } (central) applies only when x not free in v and y not free in u. This means that ACIO computations can be rearranged and discarded, but only within the limits of dataflow dependencies between the values. Working out these dependencies are the job of a compiler, exactly as with standard value declarations in Haskell. I think it should even be possible to have mutually recursive ACIO declarations, provided non-strict constructors intervene. Ian ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Interview with David Roundy on darcs and Haskell
Hi all, At osdir there is a nice interview with David Roundy about darcs, the revision control system written in Haskell. He has a few comments about Haskell as well. Read it here: http://osdir.com/Article2571.phtml This was also covered on /. (which is where I found it). /Josef ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] Re: Global Variables and IO initializers
On Thursday 25 November 2004 10:02, you wrote: This is funny. When I got no immediate reaction from you, I started implementing it myself. I ended up with something similar. It has less features but is also a lot simpler. This is the interface: initGlobal :: Typeable a = a - IO () getGlobal :: Typeable a = IO a Your implementation is probably much simpler than mine because you don't implement withEmptyDict. I'm really quite keen about withEmptyDict, because one of the MAJOR conceptual problems I have with unsafePerformIO global variables is that you only get one universe, corresponding to the Haskell program. There shouldn't really be a single the Haskell program anyway; Doesn't that run contrary to Adrian Hey's oneShot example/requirement? imagine something like GHC or an operating system written in Haskell which run sub-systems which require their own global variables. Well, that's indeed one major problems with global variables. Sure, you can try to solve it with multiple dictionaries, but that makes understanding what a certain part of the program does even harder. How do I find out what dictionary a write or read to a (no longer global) variable refers to? Furthermore, I have great difficulty in understanding why different threads need different dictionaries. Could you explain why this is useful, or rather, more useful than a global single dictionary? It reminds me of the usual thread-local variables that are offered by most systemlevel thread libraries. I think they put them in there so that they can easily port non-reentrant libraries (i.e. ones that use global variables internally) to a multi-threaded setting without changing their APIs. This approach leads to libraries that are extremely inconvenient and dangerous to use. Their existence is one of the reasons why I have been arguing so much against global variables. Storing (TypeRep,Dynamic) pairs is redundant, since Dynamics already contain their own TypeRep (that is how they are made to work). It is, but I'm not sure if it can be avoided without using stuff not in the standard libraries. What non-standard libraries have I used (that you don't)? Ben ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad
Ian Stark wrote (snipped): Way back in this thread, Koen Claessen mentioned the idea of a commutative version of the IO monad for handling things with identity. That doesn't quite do it, but I have a refinement that might. The thing is to focus on IO computations that are: a) central -- their effect commutes with every other IO action b) affine -- their effect is not directly observable, and can be discarded. Unfortunately I have a number of examples where I use global variables with initialisation actions which cannot conceivably be proven to be central affine by the compiler. For example, where I want to call up an external program (such as wish) which I will later use for doing graphics. The Haskell libraries would run into a similar problem when they tried to open stdin/stdout/stderr. Or indeed when they tried to implement RandomGen, which I presume is going to want to get at the system clock to seed the random number generator. My guess is that if we were to have top-level - actions where the actions were restricted to those certified to be ACIO, it would not be very long before GHC would implement an unsafeForceACIO function ... ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Global Variables and IO initializers
Marcin wrote (snipped): I think global variables are a lot less evil if they behave as if they were dynamically scoped, like Lisp special variables. That is, there is a construct which gives the variable a new mutable binding visible in the given IO action. It's used more often than assignment. Assignment is still available though. I agree entirely. The fact that declaring global variables using unsafePerformIO introduces an artificial notion of global and forces it on every part of the program is a major disadvantage which we haven't heard enough about in this discussion. It prevents you doing all sorts of things. It's bad for parallelism. It prevents you running two independent copies of a (main) action. It prevents you writing a Haskell controller which runs over Haskell actions as subprograms. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] Re: Global Variables and IO initializers
Benjamin Franksen wrote (snipped): Doesn't that run contrary to Adrian Hey's oneShot example/requirement? Remind me again what Adrian Hey's oneShot example/requirement is ... Well, that's indeed one major problems with global variables. Sure, you can try to solve it with multiple dictionaries, but that makes understanding what a certain part of the program does even harder. How do I find out what dictionary a write or read to a (no longer global) variable refers to? This seems to me as unnecessary as asking for which memory location it has. Provided the no-longer-global variables act as if they were global within their own universe, there is no problem. The withEmptyDict operator I provide gives you a new universe where everything starts from scratch. It seems to me you have a much bigger problem when you force everything to have global variables, and then want to run multiple copies of a program, only to have them clobber each other's variables. Furthermore, I have great difficulty in understanding why different threads need different dictionaries. Could you explain why this is useful, or rather, more useful than a global single dictionary? Consider Data.Unique implemented over lots of processors. If you had a single IORef managed by a single processor used to generate new unique identifiers, there is the danger that that processor will become a bottleneck for the whole system. Much better to have a thread-local or processor-local IORef which generates new identifiers, which you then prepend with a processor tag. Me (snipped): It is, but I'm not sure if it can be avoided without using stuff not in the standard libraries. Ben: What non-standard libraries have I used (that you don't)? OK, but you have to test every element of the dictionary with fromDynamic until you find one with the type you want, which is not a good idea if the dictionary is big. My implementation is equally inefficient now (because TypeRep's have no Ord), but if TypeRep's had Ord or a hashing function (both would be very easy to provide from GHC's implementation) I could make my implementation efficient very easily, while you'd have to completely rewrite yours to get the same effect. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] [Haskell] A puzzle and an annoying feature
[Discussion moved from Haskell to Haskell-Cafe] Hi, Regarding - lazy overlap resolution aka unique instances Well, if there's only instance which is not exported, then you can use functional dependencies. Assume class C a instance ... = C t Internally, use class C a | - a instance ... = C t Furthermore, there seems to be an issue that has been overlooked so far. - Providing sufficient type annotations Recall Lennart Augustsson writes: Here is a small puzzle. -- The following generates a type error: f :: Char - Char f c = let x = g c in h x Lennart magically inserted a type annotation to resolve the ambiguity. -- But this definition does not: f :: Char - Char f c = let x :: Bool x = g c in h x Clearly, there are a number of ways to resolve the ambiguity. The Chameleon type debugger assists the user in identifying which locations are responsible. Here's the Chameleon type debugger error message generated for the unannotated function f temp.ch:2: ERROR: Inferred type scheme is ambiguous: Type scheme: forall b. C b = Char - Char Suggestion: Ambiguity can be resolved at these locations b: f :: Char - Char f c = let x = g c ^ ^ in h x ^ ^ (The ^ correspond to highlightings of the Chameleon type debugger) This may help the user to realize where and which annotations are missing. E.g., each of the following annotations (there are more possibilities) will do the job. f :: Char - Char f c = let -- x :: Bool (1) x = g c in h x -- h (x::Bool) (2) -- (h::Bool-Char) x (3) Martin ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe