Re: [Haskell-cafe] Re: Do expression definition
On 9/13/10 6:22 AM, Michael Lazarev wrote: Thanks for examples and pointers. Since I came from Lisp, it never occurred to me that let and lambda are different constructs in Haskell. I thought that let x = y in f is really (\x - f) y It turns out that let is about declarations which are not the same as function applications above. Right. This is a common mistake for people coming from Lisp, Scheme, and other untyped lambda calculi. In the untyped world it's fine to conflate let and lambda, because they only differ in how they're typed (and if you have no types...). The difference is that, for let-bindings, once you've figured out a type of the variable being bound, then that type can be generalized. The exact process of generalization has some subtle details to watch out for, but suffice it to say that certain type variables are allowed to become universally quantified. Which means that you're allowed to use x at different types within f, provided all those different types are consistent with the generalized type. Whereas, lambda-bindings don't get generalized, and so they'll always be monomorphic (assuming Hindley--Milner inference without extensions like -XRankNTypes). This is necessary in order to catch numerous type errors, though Haskell lets you override this behavior by giving an explicitly polymorphic type signature if you have -XRankNTypes enabled. ... FWIW, a lot of the tricky details about generalization come from the way that Hindley--Milner inference is usually described. That is, since HM only allows prenex universal quantification, the quantifiers are usually left implicit. This in turn means it's not always clear when the unification variables used in type inference are actual type variables vs not. If we assume System F types instead and make all the quantifiers explicit, then it becomes much easier to explain the generalization process because we're being explicit about where variables are bound. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do expression definition
On 09/13/2010 12:23 PM, Michael Lazarev wrote: 2010/9/13 Henning Thielemannlemm...@henning-thielemann.de: It means that variables bound by let, may be instantiated to different types later. Can you give an example, please? testOk = let f = id in (f 42, f True) --testNotOk :: Monad m = m (Int, Bool) --testNotOk = do f - return id -- return (f 42, f True) Try uncommenting the 'testNotOk' definition. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Do expression definition
On 13 Sep 2010, at 10:28, Gleb Alexeyev wrote: On 09/13/2010 12:23 PM, Michael Lazarev wrote: 2010/9/13 Henning Thielemannlemm...@henning-thielemann.de: It means that variables bound by let, may be instantiated to different types later. Can you give an example, please? testOk = let f = id in (f 42, f True) --testNotOk :: Monad m = m (Int, Bool) --testNotOk = do f - return id -- return (f 42, f True) Try uncommenting the 'testNotOk' definition. There's no later here at all. Two seperate definitions in a Haskell program act as if they have always been defined, are defined, and always will be defined, they are not dealt with in sequence (except for pattern matching but that doesn't apply here). Instead, what's going on here is scoping. The f in testOk is a different f to the one in testNotOkay, distinguished by their scope. Finally, this is not how you use a let in a do expression, here's how you should do it: testOk2 :: Monad m = m (Int, Bool) testOk2 = do let f = id return (f 42, f True) Thanks Tom Davie___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do expression definition
On 09/13/2010 12:38 PM, Thomas Davie wrote: On 13 Sep 2010, at 10:28, Gleb Alexeyev wrote: On 09/13/2010 12:23 PM, Michael Lazarev wrote: 2010/9/13 Henning Thielemannlemm...@henning-thielemann.de: It means that variables bound by let, may be instantiated to different types later. Can you give an example, please? testOk = let f = id in (f 42, f True) --testNotOk :: Monad m = m (Int, Bool) --testNotOk = do f- return id -- return (f 42, f True) Try uncommenting the 'testNotOk' definition. There's no later here at all. Two seperate definitions in a Haskell program act as if they have always been defined, are defined, and always will be defined, they are not dealt with in sequence (except for pattern matching but that doesn't apply here). Instead, what's going on here is scoping. The f in testOk is a different f to the one in testNotOkay, distinguished by their scope. Finally, this is not how you use a let in a do expression, here's how you should do it: testOk2 :: Monad m = m (Int, Bool) testOk2 = do let f = id return (f 42, f True) I don't understand, I'm afraid. Michael Lazarev asked for example on the difference between let-bound and lambda-bound values. testNotOk definition mirrors the structure of the testOk definition, but testNotOk is, pardon my pun, not ok, because f is let-bound and, therefore, monomorphic, while f in the first definition is polymorphic. I never implied that definitions are processed in some sort of sequence, nor I stated that the two f's are somehow related. Thanks Tom Davie ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Do expression definition
On Mon, 13 Sep 2010, Gleb Alexeyev wrote: On 09/13/2010 12:38 PM, Thomas Davie wrote: There's no later here at all. Two seperate definitions in a Haskell program act as if they have always been defined, are defined, and always will be defined, they are not dealt with in sequence (except for pattern matching but that doesn't apply here). I don't understand, I'm afraid. Michael Lazarev asked for example on the difference between let-bound and lambda-bound values. testNotOk definition mirrors the structure of the testOk definition, but testNotOk is, pardon my pun, not ok, because f is let-bound and, therefore, monomorphic, while f in the first definition is polymorphic. I never implied that definitions are processed in some sort of sequence, nor I stated that the two f's are somehow related. I think the later refered to my words. With later I meant somewhere below the binding in the do-block. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do expression definition
On 09/13/2010 12:45 PM, Gleb Alexeyev wrote: is, pardon my pun, not ok, because f is let-bound and, therefore, monomorphic This line doesn't make sense, I was too hasty to hit the 'Send' button, I meant to write 'lambda-bound', of course, apologies for that. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Do expression definition
Thanks for examples and pointers. Since I came from Lisp, it never occurred to me that let and lambda are different constructs in Haskell. I thought that let x = y in f is really (\x - f) y It turns out that let is about declarations which are not the same as function applications above. So, here is a little followup for this experiment. Prelude :t (\f - (f 42, f True)) interactive:1:10: No instance for (Num Bool) arising from the literal `42' at interactive:1:10-11 Possible fix: add an instance declaration for (Num Bool) In the first argument of `f', namely `42' In the expression: f 42 In the expression: (f 42, f True) If I understand correctly, compiler first checks f 42, and deduces that f must be of type (Num a) = a - b. Then it checks f True, and it does not satisfy the previously deduced type for f, because type of True is not in Num class. This works: Prelude :t (\f - (f 42, f 41.9)) (\f - (f 42, f 41.9)) :: (Fractional t1) = (t1 - t) - (t, t) It just managed to deduce a type for f :: (Fractional t1) = (t1 - t) And this, of course, works: Prelude let f = id in (f 42, f True) (42,True) If I understand correctly again, it happens because f is a definition, which gets substituted to f 42 and to f True. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do expression definition
On Sep 13, 12:22 pm, Michael Lazarev lazarev.mich...@gmail.com wrote: Thanks for examples and pointers. Since I came from Lisp, it never occurred to me that let and lambda are different constructs in Haskell. You're not alone, I didn't believe my eyes when I first read about the difference (I learned Scheme, but the difference doesn't really matter here) Prelude :t (\f - (f 42, f True)) interactive:1:10: No instance for (Num Bool) [...] If I understand correctly, compiler first checks f 42, and deduces that f must be of type (Num a) = a - b. Then it checks f True, and it does not satisfy the previously deduced type for f, because type of True is not in Num class. That's a reasonable explanation - I don't know details about the order, and :t (\f - (f True, f 42)) gives the same mistake; I believe that type-checking is still in order (left-to-right or right-to-left, we can't say) but whether (Num t) and Bool is deduced first does not matter, because unifying them is commutative. This works: Prelude :t (\f - (f 42, f 41.9)) (\f - (f 42, f 41.9)) :: (Fractional t1) = (t1 - t) - (t, t) It just managed to deduce a type for f :: (Fractional t1) = (t1 - t) Yes, but that's not polymorphic in the sense people are using - ghc searched for a common type, and realized that there's a whole class of types where both 42 and 41.9 belong - Fractional. And this, of course, works: Prelude let f = id in (f 42, f True) (42,True) If I understand correctly again, it happens because f is a definition, which gets substituted to f 42 and to f True. Almost true. In evaluating let a = b, b must be evaluated before binding it to a, and a value has a type. Actually, one can define the substitution semantics you describe, but interesting things happen then. Section 22.7 of Types and Programming Languages from Pierce discusses exactly this, in the context of ML* - I guess you can also Google for let-polymorphism. The real thing is that when you write let f = id in, the type of a is deduced (internally a - a), and then generalized (internally forall a. a - a). The difference is that in the first case, GHC will try to discover what type a is by unifying it with the type of arguments of f - unification would produce type equations a = Int, a = Bool in the above example. The forall prevents that. Note that I wrote internally, even if you can actually write both types (the second with an extension, IIRC) because in many cases when you write a top-level type-signature: f :: a - a that is also implicitly generalized. * Note that in the end Pierce explains a problem with polymorphic references and its solution, but this does not applies to Haskell because of the lack of side effects (or you could say that unsafePerformIO does allow such things, and that's why it's not type- safe). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do I need to roll my own?
Hi Dave, From: David Leimbach leim...@gmail.com I'm looking at iteratee as a way to replace my erroneous and really inefficient lazy-IO-based backend for an expect like Monad DSL I've been working for about 6 months or so now on and off. The problem is I want something like: expect some String send some response to block or perhaps timeout, depending on the environment, looking for some String on an input Handle, and it appears that iteratee works in a very fixed block size. While a fixed block size is ok, if I can put back unused bytes into the enumerator somehow (I may need to put a LOT back in some cases, but in the common case I will not need to put any back as most expect-like scripts typically catch the last few bytes of data sent before the peer is blocked waiting for a response...) I'm quite sure I don't know what you're trying to do. The only time I can think of needing this is if you're running an iteratee on a file handle, keeping the handle open, then running another iteratee on it. Is this what you're doing? If so, I would make a new run function: runResidue :: (Monad m, SC.StreamChunk s el) = IterateeG s el m a - m (a, s) runResidue iter = runIter iter (EOF Nothing) = \res - case res of Done x s - return (x, s) Cont _ e - error $ control message: ++ show e This function will return the unused portion of the stream, then you can do this: enumResidue :: Handle - s - EnumeratorGM s el m a enumResidue h s = enumPure1Chunk s . enumHandle h Is this what you need? If I'm completely wrong about what you're trying to do (or you're using multiple threads), there are other options. You also may want to look at iteratee-HEAD. The implementation has been cleaned up a lot, the block sizes are user-specified, and there's an exception-based, user-extensible mechanism for iteratees to alter enumerator behavior. Sincerely, John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do I need to roll my own?
On Wed, Mar 31, 2010 at 2:12 PM, John Lato jwl...@gmail.com wrote: Hi Dave, From: David Leimbach leim...@gmail.com I'm looking at iteratee as a way to replace my erroneous and really inefficient lazy-IO-based backend for an expect like Monad DSL I've been working for about 6 months or so now on and off. The problem is I want something like: expect some String send some response to block or perhaps timeout, depending on the environment, looking for some String on an input Handle, and it appears that iteratee works in a very fixed block size. While a fixed block size is ok, if I can put back unused bytes into the enumerator somehow (I may need to put a LOT back in some cases, but in the common case I will not need to put any back as most expect-like scripts typically catch the last few bytes of data sent before the peer is blocked waiting for a response...) I'm quite sure I don't know what you're trying to do. The only time I can think of needing this is if you're running an iteratee on a file handle, keeping the handle open, then running another iteratee on it. Is this what you're doing? If so, I would make a new run function: runResidue :: (Monad m, SC.StreamChunk s el) = IterateeG s el m a - m (a, s) runResidue iter = runIter iter (EOF Nothing) = \res - case res of Done x s - return (x, s) Cont _ e - error $ control message: ++ show e This function will return the unused portion of the stream, then you can do this: enumResidue :: Handle - s - EnumeratorGM s el m a enumResidue h s = enumPure1Chunk s . enumHandle h Is this what you need? If I'm completely wrong about what you're trying to do (or you're using multiple threads), there are other options. The problem is I am not sure what it was I needed to get started to begin with. For a moment it seemed that I could be throwing out data that's been read, but not yet fed to an iteratee step. If that's not the case, I'll never need to put back any characters. The attoparsec-iteratee example posted, plus some experimentation has led me to believe I don't need to worry about this sort of thing for the kind of processing I'm looking to do. You also may want to look at iteratee-HEAD. The implementation has been cleaned up a lot, the block sizes are user-specified, and there's an exception-based, user-extensible mechanism for iteratees to alter enumerator behavior. That's very compelling. Here's the properties of the system I'm trying to build (in fact I've built this system with Haskell already months ago, but trying to evaluate if iteratee can fix problems I've got now) 1. Must have an expect-like language to a subprocess over a pair of Handles such that I can query what is normally a command line interface as a polling refresher thread to a cache. Note that there may be many sub-processes with a poller/cache (up to 6 so far). Data produced is dumped as records to stdout from each thread such that the process that spawned this haskell program can parse those records and update it's view of this particular part of the world. 2. Must be able to interleave commands between polled record data from the processes in 1. These commands come in over this process's stdin from the program that started the Haskell program. 3. The polling process in 1, must be able to respond to a timeout situation. In this system, a cable could become disconnected or a part of the system could become unavailable, or a part of the system underneath could become unreliable and require a restart to guarantee the serviceability of the whole system. I have 1 and 2 working fine in a current iteration of the system, but because we're dealing with a pretty complex stack, 3 is really necessary too, and I've conquered my timeout issues from earlier in a reasonable enough way. The problem is that the timeout handler apparently runs into problems that I think stem from lazyIO not having been evaluated on a handle yet, but the timeout handler has invalidated that handle, and then that thunk, which was partially applied, is now talking to some broken value. As far as I know, I can't go back and prevent previously bound thunks that have the wrong handle from executing, if that is truly what's happening. What I'd like to do is prevent that situation from ever happening to begin with, or at least rule it out. I'm hoping version 2 of this system to be based on iteratee and avoid this sort of problem at all. The alternative is to write this in another language, but that throws out a lot of nice and simple code that's present in the non IO bits of this code, for dealing with parsing and data serialization. Dave Sincerely, John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do we need types?
A type is, well, a type. A type class is a relation between types. The confusion probably comes from OO programming where (interfaces) describe unary relations (= one parameter type classes). (begin rant) I wouldn't easily give up algebraic data types just because OO programmers don't seem know about them - so the re-invent them and call it composite pattern... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do we need types?
A type class is a relation between types. Yes, but not officially, just de facto: http://hackage.haskell.org/trac/haskell-prime/ticket/90 Best, Maurício ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do we need types?
This seems quite relevant: http://lambda-the-ultimate.org/node/3837 titto ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do we need types?
Am Freitag 26 Februar 2010 14:07:07 schrieb Johannes Waldmann: I wouldn't easily give up algebraic data types Nor I. Without easily defined ADTs, Haskell wouldn't be nearly so awesome. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do you need Windows USB in Haskell?
I don't need usb and I can't say I'm a windows user, but I'd be glad to test it since I have it on a virtual machine. In my case, installation fails on bindings-common. bindings-common fails on windows due to an old version of C library with GHC's windows version of gcc. Current version of bindings-libusb uses bindings-DSL. I'm glad that you offered to help. But usb is not supposed to work on windows yet. The windows version of the C library has been worked on recently, so, I would need someone who would follow closely this still alpha code and maybe even sugesting adaptations to libusb-1.x build system if necessary. I don't think it's fair to expect that from someone who isn't going to use the library. Thanks! Best, Maurício ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do nmergeIO or mergeIO preserve order?
Anatoly Yakovenko wrote: do nmergeIO or mergeIO preserve order? or not preserve order? If you have a list of operations [IO a] then the future package at http://hackage.haskell.org/cgi-bin/hackage-scripts/package/future can do this. It's 'forkPromises' function returns a Chan a which can be used to get the non-order preserving results (actually Either SomeExcption a). If you are feeling lucky you can use getChanContents and filter to get a lazy [a] which is the results as they are completed. -- Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Do real programs need IO? (was IO is a bad example for Monads)
Am Montag, 10. Dezember 2007 07:05 schrieb Maurício: (...) Would you deny that any useful programme has to do at least some of the following: -accept programme arguments at invocation -get input, be it from a keyboard, mouse, reading files, pipes... -output a result or state info, to the monitor, a file, a pipe... === As long as we use current interfaces, no one would deny it. I thought Conal did, but it turned out that he just had a wider concept of RTS than I. But after reading some stuff about Epigram language, I wonder if those ideas could not be used to write a better interface to computers. Then, all those tasks would be handled by your interface plug-ins, not by programs. Really, we need to do all of that today. But I believe reading from keyboard, files etc. should not be part of programs we write daily, just a task for a basic interface to which our programs should be linked. Agreed, but until then, we need IO to write 'real' programmes. We can already encapsulate it somewhat using libs like TV, as I learnt yesterday, but even more encapsulation wouldn't be bad. Best, Maurício Cheers, Daniel ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Do real programs need IO? (was IO is a bad example for Monads)
(...) Would you deny that any useful programme has to do at least some of the following: -accept programme arguments at invocation -get input, be it from a keyboard, mouse, reading files, pipes... -output a result or state info, to the monitor, a file, a pipe... === As long as we use current interfaces, no one would deny it. But after reading some stuff about Epigram language, I wonder if those ideas could not be used to write a better interface to computers. Then, all those tasks would be handled by your interface plug-ins, not by programs. Really, we need to do all of that today. But I believe reading from keyboard, files etc. should not be part of programs we write daily, just a task for a basic interface to which our programs should be linked. Best, Maurício ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
On Dec 4, 2007 11:39 AM, Jules Bean [EMAIL PROTECTED] wrote: Ben Franksen wrote: I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. This is a straw man. Most monads will not have such a function: When I first learned monads, I heard that once you get into IO, you can never get out. The point here was that that doesn't generalize, so a student might start thinking that a monad is like a taint flag or something. Not to say that statement that it's a complete falsity when generalized to other monads -- it's reflective of the algebra of monads -- you just have to define never a little differently. :-) In any case, I don't think that's a big issue. While it is important to eliminate things that monads aren't from students' possible models, it's better just to build a good model in the first place. FWIW, the list monad was how I made the leap from monads do IO to monads do nifty stuff. Luke There is no function (State s a) - a. There is no function (r - a) - a. There is no function (Random a) - a. [assuming some random monad, often discussed] There is no function (Supply s a) - a. [Another useful monad although not one of the standard ones] There are no (total) functions Maybe a - a, [a] - a, Either e a - a. As to the topic of the thread: I agree IO is an unusual monad. I'm not sure if I agree that it shouldn't be used as a teaching basis. I think there are all kinds of ways to teach haskell; I'd be inclined to want to start with some IO, without explaining the plumbing in detail, and then come back to it later with better perspective when discussing general monads. Jules ___ 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] Re: do
Ben Franksen wrote: I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. This is a straw man. Most monads will not have such a function: There is no function (State s a) - a. There is no function (r - a) - a. There is no function (Random a) - a. [assuming some random monad, often discussed] There is no function (Supply s a) - a. [Another useful monad although not one of the standard ones] There are no (total) functions Maybe a - a, [a] - a, Either e a - a. As to the topic of the thread: I agree IO is an unusual monad. I'm not sure if I agree that it shouldn't be used as a teaching basis. I think there are all kinds of ways to teach haskell; I'd be inclined to want to start with some IO, without explaining the plumbing in detail, and then come back to it later with better perspective when discussing general monads. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do
Dan Piponi wrote: On Dec 3, 2007 1:09 PM, Denis Bueno [EMAIL PROTECTED] wrote: I don't think I can conclude that there are *no* reasons to teach the do-notation first. I just think that it is more instructive to teach it later. It's standard in mathematics teaching, when introducing a mathematical structure X, to ensure that students have the knowledge to understand an example of X before they see the definition of X. So students won't study groups before they've met the integers, they won't study fields before they've met the rationals, and they won't study topology until they're familiar with the real line. Not just met them either, usually they've usually completely internalised the examples before moving onto the general structure. Right. The problem with monads is that students have never knowingly met an example of a monad before. When one learns about Groups one hasn't met them /knowingly/ before, either. It may be that one has learned the laws that govern arithmetic; but it is not at all clear why one would want to look at one of the operations in separation, i.e. what the generality of the concept might be good for. This becomes clear only after having seen examples of a group whose elements are /not/ integers. If you teach them do-notation for IO without monads, and they get completely familiar with it (which (1) I claim is easy: http://sigfpe.blogspot.com/2007/11/io-monad-for-people-who-simply-dont.html and (2) is inevitable if they want to see the output of their programs) then when they come to learning about monads in general they'll have an example they don't even have to think about. I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. I'd rather use a simple example like Maybe (modeling failure as an effect). It can be completely understood even as a beginner, and is non-trivial enough to demonstrate the utility of the concept 'monad'. Cheers Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
On Dec 3, 2007 3:54 PM, Ben Franksen [EMAIL PROTECTED] wrote: I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. I'm not sure what a function of type m a - a has to do with the concept of a monad. And I don't really see what the problem is with the IO monad not being definable in (pure) Haskell. IO exposes the same interface as every other Monad, and you need to use that interface to get visible results. So people have to learn it whatever. And the whole point of the Monad is that it's an interface, not a specific implementation. I'd rather use a simple example like Maybe (modeling failure as an effect). And I'd like to see more people getting off the ground doing interesting stuff with Haskell before their attention spans for pointless-seeming new stuff run out. I'm not talking about the smartest people in computer science courses here. I'm talking about the millions of people writing everyday Python and Ruby scripts, say, who might benefit from a more expressive, type-safe, well-thought out, fast and compiled language. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Fw: [Haskell-cafe] Re: do
It took me forever to get comfortable with monads. I think it helps if you've seen continuations, or done FP before, or a variety of things that build familiarity. But probably the only thing that I think will work for the masses of plodders (there are always a few stars to crash the curve) is a desire to learn and tons of practice. I wouldn't worry so much about the ideal way to introduce the material. Oh, one other thing. You learn monads when you need them. You need IO right away... well, after you tired of playing with pure functions in the ghci sandbox. my 2c. t. Dan Piponi [EMAIL PROTECTED] Sent by: [EMAIL PROTECTED] 12/03/2007 07:19 PM To haskell-cafe@haskell.org cc Subject Re: [Haskell-cafe] Re: do On Dec 3, 2007 3:54 PM, Ben Franksen [EMAIL PROTECTED] wrote: I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. I'm not sure what a function of type m a - a has to do with the concept of a monad. And I don't really see what the problem is with the IO monad not being definable in (pure) Haskell. IO exposes the same interface as every other Monad, and you need to use that interface to get visible results. So people have to learn it whatever. And the whole point of the Monad is that it's an interface, not a specific implementation. I'd rather use a simple example like Maybe (modeling failure as an effect). And I'd like to see more people getting off the ground doing interesting stuff with Haskell before their attention spans for pointless-seeming new stuff run out. I'm not talking about the smartest people in computer science courses here. I'm talking about the millions of people writing everyday Python and Ruby scripts, say, who might benefit from a more expressive, type-safe, well-thought out, fast and compiled language. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe --- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
On 3 Dec 2007, at 4:19 PM, Dan Piponi wrote: On Dec 3, 2007 3:54 PM, Ben Franksen [EMAIL PROTECTED] wrote: I don't buy this. As has been noted by others before, IO is a very special case, in that it can't be defined in Haskell itself, and there is no evaluation function runIO :: IO a - a. I'm not sure what a function of type m a - a has to do with the concept of a monad. Nothing. But there are plenty of legal, safe functions of type m a - a for almost all monads m. Except those based on IO. So leading off with IO can lead to the impression that (a) monads are impossible to break out of / can't be used in purely functional code or (b) the main point of monads is to let you write imperative code in Haskell. The main point of monads is that they're so common in Haskell we'd be crazy not to call them /something/, just so we have something to say when we realize, hey, this is another of those thingies with a return and a bind! IO is quite atypical as far as the class of monads we use every day in Haskell goes; the absence of any useful, safe, pure function of type IO a - a is a (small) instance of that atypicality. IMHO, teaching IO first and then saying, monads are things that are like IO, is very counter-productive. In particular, I think it's why so few people understand the list monad (which is of course one of the pardigmatic examples). Just my 2c, of course. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do/if/then/else confusion
David Carter wrote: Another newbie question, but I can't seem to find any answers on the web... Just figured it out myself ... I need a do after the else, of course. (But I still think the error message is less than helpful!). Sorry for the bandwidth David Can someone tell me what's wrong with this? import qualified System.Posix.Directory as PD readdirAll :: PD.DirStream - IO [String] readdirAll d = do dir - PD.readDirStream d if dir == then return [] else rest - readdirAll d return (dir:rest) Compiling with GHC 6.6.1 gives me the not-very-useful message Parse error in pattern, pointing to the i of if. I've tried all kinds of alternative indentations (including indenting the else more), bracketings etc, but nothing helps. Thanks David -- The Wellcome Trust Sanger Institute is operated by Genome Research Limited, a charity registered in England with number 1021457 and a company registered in England with number 2742969, whose registered office is 215 Euston Road, London, NW1 2BE. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do/if/then/else confusion
On 11/1/07, David Carter [EMAIL PROTECTED] wrote: (But I still think the error message is less than helpful!). Maybe a bug should be filled? -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do/if/then/else confusion
(...) Can someone tell me what's wrong with this? import qualified System.Posix.Directory as PD readdirAll :: PD.DirStream - IO [String] readdirAll d = do dir - PD.readDirStream d if dir == then return [] else rest - readdirAll d return (dir:rest) (...) I don't know if this helps or disturbs, but I wrote a few different versions of your code as an exercise. If you want to try it, just uncomment the versions you want to check. The complete program below lists all files in current directory, using 'readdirAll' to get the full list. Best, Maurício module Main (Main.main) where import qualified System.Posix.Directory as PD import Data.List import Control.Monad main :: IO () readdirAll :: PD.DirStream - IO [String] readdirAll ds = liftM reverse $ read [] where read (:t) = return t read list = (PD.readDirStream ds) = glue where glue f = read (f:list) {- readdirAll ds = read where read = (PD.readDirStream ds) = rest rest = return [] rest h = liftM (h:) read -} {- readdirAll ds = do f - PD.readDirStream ds rest f where rest = return [] rest h = return (h:) `ap` (readdirAll ds) -} main = (PD.openDirStream .) = readdirAll = (putStrLn.show) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do
[EMAIL PROTECTED] wrote: Peter Verswyvelen writes about non-monadic IO, unique external worlds: But... isn't this what the Haskell compiler runtime do internally when IO monads are executed? Passing the RealWorld singleton from action to action? In GHC, yes. I never looked into any Haskell compiler. Chalmers, or York, don't remember, used continuations, this seems a bit different from the Clean approach, but I don't really know the gory details. To me, no real difference exists between IO monads and Clean's uniques types; it's just a different approach to tackle the same problem. Yes, *different approach*. So, there *are* differences. Compilers, anyway, are special applications. I wanted to see - responding to Brandon - a normal Haskell program, which does IO without monads, that't all. The problem is then when you hide something, you hide. It is possible to superpose a kind of monadic framework on unique worlds, files, etc. in Clean, but the reverse operation goes beyond my horizons. Some examples, anybody? Jerzy Karczmarczuk I don't have examples, but I can show you where the gory details are hiding: The Haskell 98 standard specifies the API for input/output to be using the IO monad. If you want to use Haskell 98 to do input/output without the IO monad then you will find that you cannot do so. I see three ways to go around Haskell98. Common caveat: The thing that using the provided IO monad does is provide a standard way of sequencing two input/output operations. Once you avoid that sequencing then you indeterminism unless you provide your own sequencing manually. The first, which you may decide does not really count, is using unsafePerformIO or unsafeInterleaveIO and avoiding the sequencing provided by the IO monad. This still does nothing to tell you about the gory details. As a cheat: If you use the FFI addendum then you can access all the impure c input/output functions and lie about their type so that are not in IO. Then you could manually manage their sequencing and control everything. This comes closer to understanding how the standard IO operations are implemented in the gory details. For the GHC implementation of Haskell it is possible to go inside the IO monad and operate using the same gory details that GHC uses. This is probably what you want to see, but note that it is not the only compiler or the only way to do this. The details are in the source at http://darcs.haskell.org/ghc-6.6/packages/base/GHC/ in IOBase.lhs and IO.hs and so on... From IOBase.lhs I see that GHC uses a newtype around a function of type State b - (State b, a) to represent IO a. The State b is actually an unboxed type State# RealWorld. The tuple is likewise an unboxed (# , #) tuple. newtype IO a = IO (State# RealWorld - (# State# RealWorld, a #)) unIO :: IO a - (State# RealWorld - (# State# RealWorld, a #)) unIO (IO a) = a Also in IOBase.lhs this is made into a Functor and, inevitably, a monad: instance Functor IO where fmap f x = x = (return . f) instance Monad IO where {-# INLINE return #-} {-# INLINE () #-} {-# INLINE (=) #-} m k = m = \ _ - k return x = returnIO x m = k = bindIO m k fail s= failIO s returnIO :: a - IO a returnIO x = IO (\ s - (# s, x #)) bindIO :: IO a - (a - IO b) - IO b bindIO (IO m) k = IO ( \ s - case m s of (# new_s, a #) - unIO (k a) new_s ) failIO :: String - IO a failIO s = ioError (userError s) -- | Raise an 'IOError' in the 'IO' monad. ioError :: IOError - IO a ioError = ioException ioException :: IOException - IO a ioException err = IO $ raiseIO# (IOException err) Where raiseIO# is from GHC.Prim http://www.haskell.org/ghc/docs/latest/html/libraries/base/GHC-Prim.html http://darcs.haskell.org/ghc/compiler/prelude/primops.txt.pp ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: do
Brandon S. Allbery KF8NH wrote: On Oct 15, 2007, at 13:32 , Peter Verswyvelen wrote: [EMAIL PROTECTED] wrote: Yes, *different approach*. So, there *are* differences. Compilers, anyway, are special applications. I wanted to see - responding to Brandon - a normal Haskell program, which does IO without monads, that't all. The problem is then when you hide something, you hide. It is possible to superpose a kind of monadic framework on unique worlds, files, etc. in Clean, but the reverse operation goes beyond my horizons. Some examples, anybody? Ah yes, I see what you mean now. I have no idea, I guess only unsafePerformIO will allow you to do something like that... But that will completely break referential transparency. But I really don't know. What do the experts have to say? Use the source of unsafePerformIO as an example of how to write code which passes around RealWorld explicitly, but without unencapsulating it like unsafePerformIO does. The main problem here, I think, is that because all the GHC runtime's functions that interact with RealWorld (aside from unsafe*IO) are themselves only exported wrapped up in IO, you can't (as far as I know) get at the lower level internal (e.g.) putStrLn' :: RealWorld - String - (# RealWorld,() #) to do I/O in a direct/explicit/non-monadic style. In theory, one could export those and use them directly. Well, if you import GHC.IOBase then you get newtype IO a = IO (State# RealWorld - (# State# RealWorld, a #)) unIO :: IO a - (State# RealWorld - (# State# RealWorld, a #)) unIO (IO a) = a Then the type of putStrLn: -- putStrLn :: String - IO () means that putStrLn' can be defined as putStrLn' :: String - State# RealWorld - (# State# RealWorld, a #) putStrLn' = unIO . putStrLn Now you have the unboxed tuple and need to work with many 'case' statements to accomplish anything. Also you need to get you hand on State# RealWorld either (1) Honestly, by wrapping your code in IO again and using it normally (2) From a copy, via unsafeInterleaveIO (3) From nowhere, via unsafePerformIO (Actually, as a practical matter, IIRC GHC knows about RealWorld and removes all of it when generating cmm code once it's done the job of sequencing Haskell evaluation; I'm not sure how well that would work if you wrote I/O in direct/explicit style. unsafePerformIO doesn't really count for that because it removes the RealWorld itself.) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
On Oct 15, 2007, at 19:00 , ChrisK wrote: Brandon S. Allbery KF8NH wrote: Use the source of unsafePerformIO as an example of how to write code which passes around RealWorld explicitly, but without unencapsulating it like unsafePerformIO does. The main problem here, I think, is that because all the GHC runtime's functions that interact with RealWorld (aside from unsafe*IO) are themselves only exported wrapped up in IO, you can't (as far as I know) get at the lower level internal (e.g.) putStrLn' :: RealWorld - String - (# RealWorld,() #) to do I/O in a direct/explicit/non-monadic style. In theory, one could export those and use them directly. Well, if you import GHC.IOBase then you get newtype IO a = IO (State# RealWorld - (# State# RealWorld, a #)) unIO :: IO a - (State# RealWorld - (# State# RealWorld, a #)) unIO (IO a) = a Then the type of putStrLn: -- putStrLn :: String - IO () means that putStrLn' can be defined as putStrLn' :: String - State# RealWorld - (# State# RealWorld, a #) putStrLn' = unIO . putStrLn Now you have the unboxed tuple and need to work with many 'case' statements to accomplish anything. Also you need to get you hand on State# RealWorld either (1) Honestly, by wrapping your code in IO again and using it normally (2) From a copy, via unsafeInterleaveIO (3) From nowhere, via unsafePerformIO (4) Honestly but unwrapped, by defining main in the same desugared way (takes State# RealWorld and returns (# State# RealWorld,a #) (or (# State# RealWorld,() #) if you stick to the H98 definition of main's type), allowing the runtime to pass it in and otherwise not doing anything other than propagating it. My real problem was that I incorrectly recalled IO's type to be based on ST, not State (i.e. had a forall to prevent anything from being able to do anything to/with the State# RealWorld other than pass it on unchanged without triggering a type error). I should have realized that was wrong because unsafePerformIO is itself expressible in Haskell (-fglasgow-exts is needed to make # an identifier character and to enable unboxed types and unboxed tuples, but does not make it possible to cross an existential type barrier). -- 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: do
On 10/15/07, ChrisK [EMAIL PROTECTED] wrote: Also you need to get you hand on State# RealWorld either (1) Honestly, by wrapping your code in IO again and using it normally (2) From a copy, via unsafeInterleaveIO (3) From nowhere, via unsafePerformIO Or you can get it honestly via lifting: liftRawIO :: (State# RealWorld - (# State# RealWorld, a #)) - IO a liftRawIO = GHC.IOBase.IO main = liftRawIO rawMain rawMain :: State# RealWorld- (# State# RealWorld, () #) {- implement rawMain here -} -- ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
Oops, I read too fast, you mentioned that as #1. On 10/15/07, ChrisK [EMAIL PROTECTED] wrote: Also you need to get you hand on State# RealWorld either (1) Honestly, by wrapping your code in IO again and using it normally Silly me. -- ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: do
I actually got this done several hours ago, but my DSL is being annoying tonight... Anyway, here's a simple example of how to do explicit/non-monadic I/O in GHC. (It *only* works in GHC; other compilers have different internal implementations of IO.) I specifically modeled it to highlight its resemblance to State. {-# OPTIONS_GHC -fno-implicit-prelude -fglasgow-exts #-} import GHC.Base import GHC.IOBase import GHC.IO import GHC.Handle (stdout) {- This is horrible evil to demonstrate how to do I/O without the help of the IO monad. And yes, it is very much a help. The trick here is that the type IO is a state-like type: a value constructor which wraps a function. Thus, working with it manually requires that we have a runIO.(*) Naively, this looks like unsafePerformIO; but in fact it is not, as unsafePerformIO uses the magic builtin RealWorld# to create a new State# RealWorld on the fly, but in fact we are passing on the one we get from somewhere else (ultimately, the initial state for main). (Additionally, we don't unwrap the resulting tuple; we return it.) This is why runIO is really *safePerformIO* (i.e. entirely normal I/O). (*) Well, not absolutely. GHC.IOBase uses unIO instead: unIO (IO f) = f I think this is a little cleaner, and better demonstrates how IO is really not all that special, but simply a way to pass state around. -} -- treat IO like State, for demonstration purposes runIO :: IO a - State# RealWorld - (# State# RealWorld,a #) runIO (IO f) s = f s -- And here's our simple hello, world demo program main :: IO () main = IO (\s - runIO (putStrLn' hello, world) s) -- this is just to demonstrate how to compose I/O actions. we could just -- call the real putStrLn above instead; it is operationally identical. -- write a string followed by newline to stdout -- this is completely normal! putStrLn' :: String - IO () putStrLn' = hPutStrLn' stdout -- write a string followed by newline to a Handle hPutStrLn' :: Handle - String - IO () hPutStrLn' h str = IO (\s - let (# s',_ #) = runIO (hPutStr' h str) s in runIO (hPutChar h '\n') s') -- write a string, iteratively, to a Handle hPutStr' :: Handle - String - IO () hPutStr' _ [] = IO (\s - (# s,() #)) hPutStr' h (c:cs) = IO (\s - let (# s',_ #) = runIO (hPutChar h c) s in runIO (hPutStr' h cs) s') -- 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