Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Daniel Fischer <[EMAIL PROTECTED]> writes: >> 'everything matters' is wrong even for IO actions, because the >> actual value returned when the action is executed is completely >> irrelevant to the IO action's identity. > Now that I cannot swallow, that would mean > return 4 == return 5. I would argue that 'return 4' (or '5') isn't an IO action (it may not even be in the IO monad, of course, but even within it.) -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
G'day all. Quoting Daniel Fischer <[EMAIL PROTECTED]>: > The sad truth is that IO actions in general aren't well defined entities > (unless we index them with the space-time-coordinates of their invocation). Not really. One of the ways that IO used to be implemented (still might be on some Haskell systems) was as a term language which was effectively interpreted by the run-time system. You could, in principle, define Eq on such a term language, assuming that there weren't any non-Eq values in subterms. So the question is relevant. > If you cannot agree, I have another question: is > > return 4 >> return 5 == return 5 > > true in the IO-Monad? It sure is: return 4 >> return 5 == return 4 >>= \x -> return 5 (defn of >>) == (\x -> return 5) 4 (return-bind law) == return 5 Now what was the question again? Cheers, Andrew Bromage ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
On Jan 24, 2005, at 8:53 PM, Jorge Adriano Aires wrote: And it would say nothing about things like: return 4 >> return 5 ==?== return 5 I can live with it. I feel obliged to point out (because the repeated references to the question are driving me up the wall) that this simple equality holds in every monad: return 4 >> return 5 === (definition of >>) return 4 >>= \_ -> return 5 === (monad laws) (\_ -> return 5) 4 === (beta reduction) return 5 We don't need to know anything about the semantics, etc. of any other actions the monad might happen to define. -Jan-Willem Maessen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
(Sorry about the recurrent self answers) > Maybe (not sure) it is sensible to > sapecify return::(a -> IO a), as an action with no side effects such that > return x === return x iff x === x. return x === return y iff x === y<-- this is what I meant to write. But even that is not enough, should be: "return x is an action with no side effects and that always returns x" The previous specification is be a consequence of this one, and it failed to specify that the returned value was always x. J.A. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
> >This isn't obvious to me. So x is an action, and it does not always > > produces the same side effects when executed. But why should that make > > x/=x? It is the same action, it gets one line from the input, and then > > prints it... > > OK, but then the different side-effects could not be used to distinguish > putStrLn "hello" >> mzero > and mzero. So I still believe, if you say these two are different, because > they produce different output, you cannot easily insist on x === x. Agree. But I don't say that. > > This I don't agree with, I think you are using the word actions for two > > different things, the elements of type IO a, and their execution. What > > you > > You're right, but one of my problems is to identify elements of type IO a. > If the returned value isn't the thing, the execution must matter, but which > parts of the execution are to be taken into account? How can we tell if functions f === g? They must have the same domain, codomain and return the same result for every element of the domain. This is just the mathematical definition. For any two arbitrary functions f,g, can you tell if they are the same or not? As a definition, I'd be happy to have, x,y :: IO a are the same if, given the same, real world, they produce the same effects and return the same result. Now I'm not saying we can derive that x === x, for x ::IO, from that, but it is certainly consistent with that point of view, so we can take it as an axiom. Which I think we already do. We also have that if f === g than f x === g x. That includes functions of type f,g :: a -> IO b. All seems consistent. Any other "equality" relation should include that one. Is it enough? It's enough to be able to tell that: putStrLn "hello" >> return 3 === putStrLn ("he"++"llo") >>=\ _ return (1+2) And it would say nothing about things like: return 4 >> return 5 ==?== return 5 I can live with it. To prove that two functions are in deed the same, we may use, say, number theory knowledge, which falls outside the scope of haskell. I find it sensible to do the same with actions. Maybe (not sure) it is sensible to specify return::(a -> IO a), as an action with no side effects such that return x === return x iff x === x. If we add that to our knowledge of IO, along with an appropriate specification for (>>=), then we would have: return 4 >> return 5 === return 5 J.A. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is a stack overflow?
hi, it may happen for different reasons, but a common one is when you have a foldl pattern (programming with an accumulator), for example like this: sumList1 [] accum = accum sumList1 (x:xs) accum = sumList1 xs (x + accum) this adds a list of numbers with an accumulator. because haskell is lazy however, the additions (the accumulator) are not evaluated, instead the compiler builds a big expression, that is to be evaluated later. for example: sumList1 [1,2,3] 0 = sumList1 [2,3] (1 + 0) = sumList1 [3] (2 + (1 + 0)) = sumList1 [] (3 + (2 + (1 + 0)) = 3 + (2 + (1 + 0) notice that the accumlator is not evaluated as you go along. now the way this expression is evaluated (roughly) is: start pushing... (stack on the rhs) 3 + (2 + (1 + 0) [] 2 + (1 + 0)[3] 1 + 0[2,3] 0 [1,2,3] now poping... 1 [2,3] 3 [3] 6 [] and the result is 6. if the list is very long, you will need to push very many things on the stack to evaluate the expression, and so you might run out of stack. the way to avoid this problem is to not create the big expression, by forcing the accumulator to be evaluated "as you go along" rather then once at the end. this can be done like this: sumList2 [] accum = accum sumList2 (x:xs) accum = sumList2 xs $! (x + accum) ($!) is like ($) except that it forces the evaluation of its arguments. now the expression is likely to be evaluated using very little stack (if the compiler notices that we have a tail recursive call, and it should) hope this helped -iavor On Mon, 24 Jan 2005 19:19:09 -0500 (Eastern Standard Time), S. Alexander Jacobson <[EMAIL PROTECTED]> wrote: > Thank you iavor. But the -K option doesn't appear > to work with ghci. And I guess the bigger > question is what sort of code causes a > stack overflow. If 5M is enough stack for most > programs then I obviously have some basic coding > error which is causing a stack overflow... > > What sort of code causes that? > > -Alex- > __ > S. Alexander Jacobson tel:917-770-6565 http://alexjacobson.com > > On Mon, 24 Jan 2005, Iavor Diatchki wrote: > > > hi, > > programs compile with GHC have a bunch of command line switches. > > you can see them by typing: > > myProg +RTS -help > > one of them enables you to specify stack space, e.g. > > myPorg +RTS -K5M > > > > (very briefly) the stack is a part of memory used by the compiler to > > pass around arguments > > to functions, and for temporary computations. > > -iavor > > > > > > > > > > On Mon, 24 Jan 2005 17:16:08 -0500 (Eastern Standard Time), S. > > Alexander Jacobson <[EMAIL PROTECTED]> wrote: > >> GHC assumes the user knows the difference between > >> the heap and the stack. I don't. No matter how > >> much heap I specify on the GHCi command line, I > >> get a stack overflow exception. I have no idea > >> what that means or how to remedy it. Hints? > >> > >> Note: My program is basically creating a few 100k > >> item FiniteMaps. I don't think that should exceed > >> the memory on my laptop > >> > >> -Alex- > >> > >> __ > >> S. Alexander Jacobson tel:917-770-6565 http://alexjacobson.com > >> ___ > >> 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 > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] what is a stack overflow?
Thank you iavor. But the -K option doesn't appear to work with ghci. And I guess the bigger question is what sort of code causes a stack overflow. If 5M is enough stack for most programs then I obviously have some basic coding error which is causing a stack overflow... What sort of code causes that? -Alex- __ S. Alexander Jacobson tel:917-770-6565 http://alexjacobson.com On Mon, 24 Jan 2005, Iavor Diatchki wrote: hi, programs compile with GHC have a bunch of command line switches. you can see them by typing: myProg +RTS -help one of them enables you to specify stack space, e.g. myPorg +RTS -K5M (very briefly) the stack is a part of memory used by the compiler to pass around arguments to functions, and for temporary computations. -iavor On Mon, 24 Jan 2005 17:16:08 -0500 (Eastern Standard Time), S. Alexander Jacobson <[EMAIL PROTECTED]> wrote: GHC assumes the user knows the difference between the heap and the stack. I don't. No matter how much heap I specify on the GHCi command line, I get a stack overflow exception. I have no idea what that means or how to remedy it. Hints? Note: My program is basically creating a few 100k item FiniteMaps. I don't think that should exceed the memory on my laptop -Alex- __ S. Alexander Jacobson tel:917-770-6565 http://alexjacobson.com ___ 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: what is inverse of mzero and return?
Am Montag, 24. Januar 2005 22:59 schrieb Benjamin Franksen: > Both are wrong. 'just the result matters' is the correct POV for functions, > but not for IO actions. 'everything matters' is wrong even for IO actions, > because the actual value returned when the action is executed is completely > irrelevant to the IO action's identity. Now that I cannot swallow, that would mean return 4 == return 5. I suppose you didn't mean that, though. Maybe, the internal workings are irrelevant, only visible side-effects and the returned value? But which side-effects are relevant? > And also some of the electrons on transistor 19348587434 on the CPU chip > move with a slightly reduced velocity due to the computer user shouting > curses at his machine... could that alter the number of reductions? > > Seriously, the model in which the 'sameness' resp. identity of IO actions > is defined takes into account only (a subset of all) externally observable > effects, not the way a certain interpreter/compiler executes the action > internally. > > I'll stop here; think I have made my point Yes, and I still don't know which effects do count and why these and not others. > > Ben > ___ > 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: what is inverse of mzero and return?
Am Dienstag, 25. Januar 2005 00:29 schrieb Jorge Adriano Aires: >> x = getLine >>= putStrLn >This isn't obvious to me. So x is an action, and it does not always produces >the same side effects when executed. But why should that make x/=x? It is the >same action, it gets one line from the input, and then prints it... OK, but then the different side-effects could not be used to distinguish putStrLn "hello" >> mzero and mzero. So I still believe, if you say these two are different, because they produce different output, you cannot easily insist on x === x. >A constant c :: a is just morphism(function) c : 0 -> a, where 0 is the >initial object (empty set). ^ The empty set being an initial object means, for every a there is exactly one morphism from 0 to a. A constant is a function from a one-element-set to a. > This I don't agree with, I think you are using the word actions for two > different things, the elements of type IO a, and their execution. What you You're right, but one of my problems is to identify elements of type IO a. If the returned value isn't the thing, the execution must matter, but which parts of the execution are to be taken into account? > just showed is that those IO () elements (actions) when executed, always > created different side effects in the real world. Not that the actions > themselves are different. But that is the problem, what does it mean for two actions to be the same? After all, writing "hello" to stdout is just a side-effect, like putting 4 on the stack and immediately ignoring it. > > J.A. > ___ > 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: what is inverse of mzero and return?
> A constant c :: a is just morphism(function) c : 0 -> a, where 0 is the > initial object (empty set). --- Rant2 "correction" Opss I messed up here. Should be terminal should 1-> a (terminal object/unit set). At least that's how I usually think of constants in haskell 1 is ()... so I think I don't know what is a constant in Haskell... Anyway, stopping now. J.A. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Am Montag, 24. Januar 2005 20:25 schrieb Keean Schupke: > I think the endofunctors are defined on the types, not the values > though. So the object of the category is the endofunctor (Type -> Type), > and unit and join are the identity and binary associative operator on > which a Monad is defined. return and bind are defined in terms of unit > and join. So unit is the identity which when joined to the endofunctor > (Type -> Type) results in the same endofunctor... Therefor: > > (Type -> Type) `join` unit => (Type -> Type) > > Now as the type of the IO monad is "IO a" we end up with: > > (IO a -> IO a) `join` unit => (IO a -> IO a) > > This is true irrespective of any side effects IO may have, as the type > is the > same for the IO action no matter what side effects it generates. > > At least thats how I understand it... > > Keean. > You lost me there. As I see it, the objects of C are the types, i.e. Ob(C) = {T : T is a Haskell type}. I'd say that a type is a set of values, but that doesn't matter really. The Morphisms of C are the functions between types, i.e. Mor(A, B) = {f : A -> B}. Then IO is (supposed to be) a functor C -> C, that is, to every object A we have an associated one, namely IO(A), and to every morphism f `elem` Mor(A,B) we have an associated one, IO(f) `elem` Mor(IO(A), IO(B)). Further we have a natural transformation, eta, from the identity functor to IO, that is, for every A `elem` Ob(C) we have an eta_A `elem` Mor(A, IO(A)), such that (forall A,B `elem` Ob(C)) (forall f `elem` Mor(A, B)) (eta_B . f == IO(f) . eta_A) and a natural transformation mu from IO . IO to IO, that is, for every A `elem` Ob(C) we have a mu_A `elem` Mor(IO(IO(A)), IO(A)), such that (forall A,B `elem` Ob(C)) (forall f `elem` Mor(A, B)) (mu_B . IO(IO(f)) == IO(f) . mu_A). Now, eta is return and mu is join, or mu_A = (>>= id_(IO(A))). Finally, in order to make the triple (IO, eta, mu) a Monad, eta and mu must meet three conditions: i) mu . IO(mu) = mu . mu, or, more clearly (forall A `elem` Ob(C)) (mu_A . IO(mu_A) == mu_A . mu_(IO(A))), ii) mu . eta == id, or (forall A `elem` Ob(C)) (mu_A . eta_(IO(A)) == id_(IO(A))), iii) mu . IO(eta) == id, or (forall A `elem` Ob(C)) (mu_A . IO(eta_A) == id_(IO(A))). Each of these conditions demands the equality of some functions, and all of these functions are in Mor(A, IO(B)) for appropriate A and B. So the first question to answer -- and I believe the rest will relatively easily follow from that answer -- is What does equality mean in type IO(A)? Without that, the conditions are meaningless, and IO cannot even be a functor. And suppose we found an answer, such that indeed IO is a functor. Are then conditions i)--iii) fulfilled? Condition ii) demands that return (putStrLn "hi") >>= id == putStrLn "hi". Let's try it out: Prelude> putStrLn "hi" hi (16 reductions, 30 cells) Prelude> return (putStrLn "hi") >>= id hi (22 reductions, 36 cells) Now obviously they aren't absolutely identical, in return .. >>= id, we execute the actions of first wrapping up putStrLn "hi" in a further IO-layer and then unwrapping it again. So if we insist that equality of IO-actions means that exactly the same actions are performed, IO is NOT a Monad. But I don't suppose such a rigid interpretation was intended and in our running example, there was additional output generated, which is a visible difference. But is it so important whether WE see a difference or only the machine does? Of course, saying that two IO-actions are equal when they return the same result (given the same input), is not easily accepted, but output isn't the perfect criterion either: what if stdout is closed? Is putStrLn "hello" >> mzero == mzero then? I wish someone called Simon could shed some light on this issue. Daniel ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
> We face a severe problem here, not only that IO a is not an instance of Eq, > which takes this whole discussion outside the realm of Haskell, on top of > > that we find the horrible fact that x /= x may be true in the IO Monad, > consider > > x = getLine >>= putStrLn > > or anything similar -- actually we already have getChar /= getChar This isn't obvious to me. So x is an action, and it does not always produces the same side effects when executed. But why should that make x/=x? It is the same action, it gets one line from the input, and then prints it... In fact, I do not agree. See Rant 2 below. > The sad truth is that IO actions in general aren't well defined entities > (unless we index them with the space-time-coordinates of their invocation). > So I suggest ending the discussion by agreeing that the question whether or > not > x >> mzero == mzero > holds in the IO-Monad is meaningless (at least, it's fruitless). > If you cannot agree, I have another question: is > > return 4 >> return 5 == return 5 > > true in the IO-Monad? Yeap, I thought about it too, have no idea, and cannot afford to spend much time thinking about it now either, since I got work to do... :-/ --- Rant 1 My gut feeling would be no. I think my intuitive reasoning is too just consider that, every IO action is equal to itself, then take the closure with respect to function application, and assume all others cannot be proved. That is, x === x, for all x :: IO a f x === g x, for all x :: a and f,g :: a -> IO b, such that f === g Where equality between functions is defined the usual way. --- Rant 2 Nope, we have to have getChar === getChar. I think you'll agree if I say that we have: 1. return === return 2- return 5 === return 5 return 5 >> return 5 === return 5 >> return 5 Because this has nothing to do with IO. 1. We have that, return :: a->IO a is a function, not an action, so it must be equal to itself. 2. We have that, return :: a->IO a is a function, not an action, so it must return the same value when applied to the same element. 3. (>>) :: (Monad m) => m a -> m b -> m b It is also a function, so (>>) x === (>>) x. And by the same reasoning (>>) x y === (>>) x y. So from 2 we have 3. A constant c :: a is just morphism(function) c : 0 -> a, where 0 is the initial object (empty set). So we must have c === c. Which means getChar === getChar. In other words, by questioning wether you can have x ==/= x for x :: IO a, you are questioning wether we really have f === f for all functions f::a->b. --- > > return "hello" >>= putStrLn > > > > this does not only have the same type as putStrLn "hello", and return > > the same value (), but it also carries out exactly the same actions. > > But does it really? hugs thinks otherwise: > Prelude> putStrLn "hello" > hello > () > (28 reductions, 55 cells) > Prelude> return "hello" >>= putStrLn > hello > () > (31 reductions, 56 cells) > Prelude> putStrLn "hello" > hello > () > (26 reductions, 50 cells) > > even the same input does not necessarily lead to exactly the same actions, > depending on whether "hello" is already known or not. This I don't agree with, I think you are using the word actions for two different things, the elements of type IO a, and their execution. What you just showed is that those IO () elements (actions) when executed, always created different side effects in the real world. Not that the actions themselves are different. J.A. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
On Monday 24 January 2005 21:23, Daniel Fischer wrote: > Am Montag, 24. Januar 2005 11:47 schrieb Jules Bean: > > > > Here are the three monad laws as written on the nomaware site: > > > > 1. (return x) >>= f == f x > > 2. m >>= return == m > > 3. (m >>= f) >>= g == m >>= (\x -> f x >>= g) > > > > Taking rule 1, we do not simply mean that return x >>= f and f x have > > the same type. (This is obviously true). We require that they are equal > > as values of the type m a. In the case of IO, this means that they > > perform the same action before yielding the same result. > > We face a severe problem here, not only that IO a is not an instance of Eq, > which takes this whole discussion outside the realm of Haskell, on top of > that we find the horrible fact that x /= x may be true in the IO Monad, > consider > > x = getLine >>= putStrLn > > or anything similar -- actually we already have getChar /= getChar I wonder how you derive at this strange conclusion. Of course, getChar == getChar is always true. Now we clearly have to say what we mean by this kind of equality. Well, there is an operational model of the program inside its environment (OS, etc..) in identity resp. equality of IO actions are defined with respect to this model. For instance: getChar = 'the action that, when executed, reads a character from stdin and returns it' > and that holds whether we just consider the values returned by an IO action > or take the action performed into account. > The sad truth is that IO actions in general aren't well defined entities I think the above definition is quite well defined. > (unless we index them with the space-time-coordinates of their invocation). No need to do that. > So I suggest ending the discussion by agreeing that the question whether or > not > x >> mzero == mzero > holds in the IO-Monad is meaningless (at least, it's fruitless). It is obviously plain wrong. > If you cannot agree, I have another question: is > > return 4 >> return 5 == return 5 > > true in the IO-Monad? Why, yes of course. That doesn't mean you can generalize it arbitrarily. It is true, because 'return 4' has no effect, other than returning '4' which is ignored by the '>>' operator. In our operational model, 'return 4 >> return 5' has exactly the same externally visible effect as 'return 5', so they are equal. > >From the 'just the result matters'-point of view, obviously. > >From the 'everything matters'-point of view not. Both are wrong. 'just the result matters' is the correct POV for functions, but not for IO actions. 'everything matters' is wrong even for IO actions, because the actual value returned when the action is executed is completely irrelevant to the IO action's identity. > I feel a little more at home with the former, because it matches the > extensional equality of set theory, but I'm not happy with either. > For any mathematician, the function > \x -> 2*sin x * cos x > IS the same function as > \x -> sin (2*x) > (given the equality of their respective domains -- though, for ghc they > aren't, due to rounding errors), The above equality depends on what sin and cos mean. Regarded as functions on real numbers it is correct. It is false if they are considered functions on floating point numbers (and thus only approximating the 'real' sin/cos). > so if we transport this extensionality to > our problem -- I am aware that is problematical because of the side-effects > -- we get > putStrLn "hello" >> mzero == mzero. As I said, this is complete nonsense. > > Example: > > > > return "hello" >>= putStrLn > > > > this does not only have the same type as putStrLn "hello", and return > > the same value (), but it also carries out exactly the same actions. > > But does it really? hugs thinks otherwise: > Prelude> putStrLn "hello" > hello > () > (28 reductions, 55 cells) > Prelude> return "hello" >>= putStrLn > hello > () > (31 reductions, 56 cells) > Prelude> putStrLn "hello" > hello > () > (26 reductions, 50 cells) > > even the same input does not necessarily lead to exactly the same actions, > depending on whether "hello" is already known or not. And also some of the electrons on transistor 19348587434 on the CPU chip move with a slightly reduced velocity due to the computer user shouting curses at his machine... Seriously, the model in which the 'sameness' resp. identity of IO actions is defined takes into account only (a subset of all) externally observable effects, not the way a certain interpreter/compiler executes the action internally. I'll stop here; think I have made my point Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] what is a stack overflow?
GHC assumes the user knows the difference between the heap and the stack. I don't. No matter how much heap I specify on the GHCi command line, I get a stack overflow exception. I have no idea what that means or how to remedy it. Hints? Note: My program is basically creating a few 100k item FiniteMaps. I don't think that should exceed the memory on my laptop -Alex- __ S. Alexander Jacobson tel:917-770-6565 http://alexjacobson.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] File path programme
Isaac Jones wrote: >You might be interested in the new FilePath module that's in the >works. There's been a lot of work to make these functions portable. > >http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/libraries/base/System/FilePath.hs I didn't realize this was in CVS. IMHO this library is deeply broken, and should not be in GHC 6.4. We should be replacing ill-specified hacks with a carefully designed library, not an official collection of ill-specified hacks. It took me only a few minutes to find a bunch of cases which the CVS code mishandles, ranging from simple bugs, to cases where the existing behavior might be okay if documented, to cases where I'm not convinced there's any sensible behavior consistent with the function's type. (Win32) splitFileName "server\\share" ==> ("server","share") (should probably be ("server\\share","")) splitFileName "foo:xyz" ==> ("foo:.","xyz") (should be (".","foo:xyz") -- this refers to the named stream xyz of foo) joinPaths "c:\\" "\\foo" ==> "\\foo" (should be "c:\\foo". I realize that "cd c:\\" on Windows doesn't actually make "c:\\" the current directory, but ";" doesn't separate shell commands either.) (Posix) splitFileName "/foo" ==> ("/","foo"), splitFileName "/foo/" ==> ("/foo","") (arguably makes sense, but why isn't it documented?) splitFileName "/foo/bar" ==> ("/foo","bar") splitFileName "/foo//bar" ==> ("/foo/","bar") (definitely a bug) pathParents "/foo///bar" ==> ["/","/foo","/foo","/foo","/foo/bar"] pathParents "foo/../bar" ==> [".","foo/../bar"] (what if foo doesn't exist and we wanted to create it?) Add to those the fundamental problems with splitFileExt which were already mentioned on this thread. I don't even think the broad approach taken by the library interface is right. Manipulating pathnames with FilePath->FilePath functions is like refactoring a Haskell module with String->String functions. There should be parsing and serialization functions which convert between the external FilePath representation and an internal ADT, and the manipulation should happen on the ADT. Please, let's not ship this with the hierarchical libraries. It's not ready for prime time. -- Ben ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Am Montag, 24. Januar 2005 11:47 schrieb Jules Bean: > Here are the three monad laws as written on the nomaware site: > > 1. (return x) >>= f == f x > 2. m >>= return == m > 3. (m >>= f) >>= g == m >>= (\x -> f x >>= g) > > Taking rule 1, we do not simply mean that return x >>= f and f x have > the same type. (This is obviously true). We require that they are equal > as values of the type m a. In the case of IO, this means that they > perform the same action before yielding the same result. We face a severe problem here, not only that IO a is not an instance of Eq, which takes this whole discussion outside the realm of Haskell, on top of that we find the horrible fact that x /= x may be true in the IO Monad, consider x = getLine >>= putStrLn or anything similar -- actually we already have getChar /= getChar and that holds whether we just consider the values returned by an IO action or take the action performed into account. The sad truth is that IO actions in general aren't well defined entities (unless we index them with the space-time-coordinates of their invocation). So I suggest ending the discussion by agreeing that the question whether or not x >> mzero == mzero holds in the IO-Monad is meaningless (at least, it's fruitless). If you cannot agree, I have another question: is return 4 >> return 5 == return 5 true in the IO-Monad? From the 'just the result matters'-point of view, obviously. From the 'everything matters'-point of view not. I feel a little more at home with the former, because it matches the extensional equality of set theory, but I'm not happy with either. For any mathematician, the function \x -> 2*sin x * cos x IS the same function as \x -> sin (2*x) (given the equality of their respective domains -- though, for ghc they aren't, due to rounding errors), so if we transport this extensionality to our problem -- I am aware that is problematical because of the side-effects -- we get putStrLn "hello" >> mzero == mzero. > > Example: > > return "hello" >>= putStrLn > > this does not only have the same type as putStrLn "hello", and return > the same value (), but it also carries out exactly the same actions. But does it really? hugs thinks otherwise: Prelude> putStrLn "hello" hello () (28 reductions, 55 cells) Prelude> return "hello" >>= putStrLn hello () (31 reductions, 56 cells) Prelude> putStrLn "hello" hello () (26 reductions, 50 cells) even the same input does not necessarily lead to exactly the same actions, depending on whether "hello" is already known or not. > > If it was simply enough that it have the same type, then it would be > 'good enough' if > > return "hello" >>= putStrLn > > had the same effect as > > putStrLn "goodbye" > > ...which has the same type, and the same return value. Yes, definitely a point, if only the result matters, we must say putStrLn "hello" == putStrLn "goodbye", which is somewhat counterintuitive. On the other hand, there are many counterintuitive truths around. > > Aside: you said a couple of messages ago: > > Yes it is, side effects are quite clearly not counted. The value > > of (putStrLn "Hello" >> mzero") is mzero. > > This concept of 'value' only makes sense in some monads. In the List > monad there can be many 'values' of a computation. It just happens that > IO 'returns' a 'single value' all the time. Yes, and return "hello" returns the value "hello", so the concept of value absolutely makes sense in the IO-Monad -- though I would prefer to call "hello" the 'result' of the IO-action, rather than the 'value'. And the result of x >> mzero is mzero, regardless of what x is. Keean: >Just thinking about this, a monad is a Functor plus two >natural-tranformations, Unit and Join. Is there an equivalent definition >for MonadPlus... I am not sure I understand where MonadPlus comes from? >Is it just a Functor and two different definitions of Unit and Join >(from those chosen to be in the class Monad?) > >Keean. And these two transformations must satisfy certain conditions. As for MonadPlus, it's just a Monad m with the additional property that forall objects a, the object m(a) is a monoid -- if I'm not mistaken, it also defines a Functor into the category of monoids in our three cases and should do anyway (that's something different from the fact that the object m(a) is a monoid, additionally we must have that for all maps f: a -> b, the associated map fmap f (which should be liftM f) is a monoid-homomorphism; however if we view m as a functor into category Mon, it is no longer a Monad, because then even the concept of a natural transformation of Id to m isn't defined, since these are functors to different categories). I haven't yet figured out, why exactly mzero >> x and x >> mzero must always yield mzero, that is, the exact interplay between 'bind' and 'fmap', but in our three cases it's natural enough (pace Ashley, Jules and everybody else: if we take the 'results only'-point o
Re: [Haskell-cafe] Re: Hugsvs GHC (again)was: Re: Somerandomnewbiequestions
Ketil Malde wrote: > > The point is that the Unix documentation does not consider the short > > pause as data is read off your hard drive to be blocking. So that's why > > select will always report that data is available when you use it with a > > file handle. > > Isn't this also for historic reasons? Partly. But I think that it's also because this functionality wasn't intended for the purpose which is being discussed, i.e. enabling a process to obtain maximal CPU utilisation. For that purpose, explicit overlapped I/O (in all forms) can only ever be a partial solution, because you still have the issue that "memory" (i.e. code/data/stack segments) is demand-paged. The only solution there is multiple threads. -- Glynn Clements <[EMAIL PROTECTED]> ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Hugsvs GHC (again)was: Re: Somerandomnewbiequestions
David Roundy wrote: > > >If you're reading from a random-access file, there's no way it can > > >tell you when the file data is buffered, because it doesn't know which > > >part of the file you plan to read. The OS may try to guess for > > >readahead purposes, but select()'s behavior can't depend on that guess. > > > > But surely it does! read only reads the next block... to skip randomly > > you must seek... therefore the following sequence does this: > > > > seek > > select > > read > > > > The select should block until one disk block from the file is in memory, > > read is defined such that it will return if some data is ready even if it > > is not as much as you requested. So in this case if you ask for a > > complete file, you may just get one block... or more. > > > > In other words the API restricts reads to the 'next' block - so seek > > knows which block needs to be read into memory... > > Wouldn't select always fail, since the block would never be read into > memory until you call read? True, unless calling select() automatically triggered read-ahead (which isn't an unreasonable idea). In that regard, select/poll is different from non-blocking and asynchronous I/O. With the latter, you're explicitly asking for data to be read. -- Glynn Clements <[EMAIL PROTECTED]> ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Jules Bean wrote: I've lost track of what you mean by 'this case' and indeed of what you mean by 'join' (did you mean mplus? the word join is normally used for the operation of type m (m a) -> m a, which is not often used directly in haskell) However, even addressing your point about endofunctors: for two endofunctors to be equal, they must be equal on all objects and all morphisms, which effectively means they must be pointwise equal on all values. Jules I think the endofunctors are defined on the types, not the values though. So the object of the category is the endofunctor (Type -> Type), and unit and join are the identity and binary associative operator on which a Monad is defined. return and bind are defined in terms of unit and join. So unit is the identity which when joined to the endofunctor (Type -> Type) results in the same endofunctor... Therefor: (Type -> Type) `join` unit => (Type -> Type) Now as the type of the IO monad is "IO a" we end up with: (IO a -> IO a) `join` unit => (IO a -> IO a) This is true irrespective of any side effects IO may have, as the type is the same for the IO action no matter what side effects it generates. At least thats how I understand it... Keean. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
> Right, but we are dealing with the type system here. Remember Haskell > monoids are functors on types, not on values ... (ie the base objects the > 'category theory' is applied to are the types not the values)... > > Therefore we only consider the types when considering Monads. How so? Functors map morphisms and objects from one category into another. class Functor f where fmap :: (a->b) -> f b -> f a We have the two maps there. - The type constructor, maps the objects (types). - The fmap higher order function, maps the morphisms (function between types). Monads are, in particular, functors. So again, the type constructor maps the objects (types) and the mapping on morphisms (functions from one type to the other) is given by liftM (that is, fmap = liftM). Like Ashley Yakeley said, we can have many different functions (morphism) between two types, namely IO a types. > As such if you wished to consider the examples you gave distinct, the > type system would need to distinguish side effects... Why? I don't see how side effects make any difference here... How do you distinguish morphisms f and g: f,g :: Int -> Int f n = 2*n g n = 2+n J.A. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
On 24 Jan 2005, at 18:18, Keean Schupke wrote: Ashley Yakeley wrote: If you remember your category theory, you'll recall that two morphisms are not necessarily the same just because they're between the same two objects. For instance, the objects may be sets, and the morphisms may be functions between sets: morphisms from A to B are the same only if they map each element in A to the same element in B. Yes, but I though the 'objects' in this case are endofunctors from a type to itself... the the morphisms operate on these endofunctors, the morphisms are unit and join such that joining 'unit' to the endofuntor retults in the endofunctor. But I think that as the endofunctor is from the type to itself, the value does not come into it. I've lost track of what you mean by 'this case' and indeed of what you mean by 'join' (did you mean mplus? the word join is normally used for the operation of type m (m a) -> m a, which is not often used directly in haskell) However, even addressing your point about endofunctors: for two endofunctors to be equal, they must be equal on all objects and all morphisms, which effectively means they must be pointwise equal on all values. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Ashley Yakeley wrote: If you remember your category theory, you'll recall that two morphisms are not necessarily the same just because they're between the same two objects. For instance, the objects may be sets, and the morphisms may be functions between sets: morphisms from A to B are the same only if they map each element in A to the same element in B. Yes, but I though the 'objects' in this case are endofunctors from a type to itself... the the morphisms operate on these endofunctors, the morphisms are unit and join such that joining 'unit' to the endofuntor retults in the endofunctor. But I think that as the endofunctor is from the type to itself, the value does not come into it. A -> A `join` unit => A -> A Keean. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Hugs for Zaurus
On Mon, Jan 24, 2005 at 04:48:49PM +, Graham Klyne wrote: > At 20:15 21/01/05 +, John Goerzen wrote: > >I have built a fixed Hugs for the Zaurus PDA running the OpenZaurus > >distribution. Download here: > >http://quux.org/devel/zaurus/hugs_hugs98-Nov2003-r1_arm.ipk > > Cool! > > I've often thought Haskell should be a good language for programming PDA > functions, as a kind of super-calculator. Now I've seen versions mentioned > for two PDAs, but no Palm yet. Out of curiosity, do you know what the other PDA is? I suspect the reason there's nothing for Palm is because one probably can't just port to it in the normal sense. For isntance, until recently, PalmOS had no notion of a filesystem, though it does have simplistic database functions built in and a type/creator thing similar to older versions of MacOS. Memory is also quite constrained on many Palms, and I think management is different than in standard C, but I'm not certain of that. The port to Zaurus is easy because it is a real OS (Linux) on it. Even comes with a terminal emulator. And one can run Debian or X (www.pdaxrom.org) on it, too. It's a good PDA for a geek :-) -- John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] File path programme
At 15:17 20/01/05 -0500, Mark Carroll wrote: I tried writing a little command-line utility to find the relative path of one thing from another thing (with Unix-like systems in mind). ... FWIW, there's logic to do something like this in my URI module [1]. Bear in mind that there is not, in general, a unique solution (e.g. in extremis, the absolute path of the target might be a legitimate solution, regardless of the base). [1] http://www.ninebynine.org/Software/HaskellUtils/Network/URI.hs There's also a slightly later copy in the Haskell libraries CVS, which I believe is due to ship with the next GHC release. Look for function relativeFrom. See also module URITest.hs [2], for examples of relative paths created by this algorithm (look for function testRelSplit). [2] http://www.ninebynine.org/Software/HaskellUtils/Network/URITest.hs #g -- At 15:17 20/01/05 -0500, Mark Carroll wrote: I tried writing a little command-line utility to find the relative path of one thing from another thing (with Unix-like systems in mind). For example, $ ./pathfromof /etc/init.d/ /etc/X11/XF86Config-4 ../X11/XF86Config-4 $ ./pathfromof /tmp/baz/ /tmp/foo/ . $ ls -l /tmp/baz lrwxr-xr-x 1 markc markc 8 2005-01-20 12:01 /tmp/baz -> /tmp/foo It turned out surprisingly complex, though, and doesn't feel very neat or tidy at all, nor is it very portable given that I couldn't find generic library functions for manipulating bits of filepaths. Anyhow, it's at http://www.chiark.greenend.org.uk/~markc/PathFromOf.hs and may yet have egregious bugs. It seems to me like it could certainly be improved in various ways. If anyone has any thoughts, as to how I could improve my style, make more use of standard libraries, etc., I'd certainly appreciate them. Thanks, Mark ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] HaXmL and the IO Monad
At 14:53 21/01/05 +, John Goerzen wrote: I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that. Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type: I just saw David Roundy's response, and think that's way better than my approach (below). In my modifications to HaXml [1], in re-working the external entity inclusion, I did indeed resort to using unsafePerformIO (which may be original HaXml, I don't recall). Later, I thought of a cleaner approach which would be to make the XML parsing parameterized (somehow, I forget the details right now) on a monadic function for entity retrieval. For calling functions that don't want to be forced into the IO monad, use an identity monad, which in turn would not allow external entities, otherwise use an IO function. This approach is specialized to a particular use of IO, and requires modifying the HaXml code. When I get time (not in the foreseeable future), it's a change I'd like to apply to get rid of the unsafePerformIO. I already have alternative parsing functions with/without external entity support to distinguish internal and external XML subset cases. I haven't actually worked out the details for using a monad, so I could be completely deluded here. [1] http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/ Specifically: http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXml/SubstitutePE.hs which currently has alternative functions peNullResolver and peExtResolver to handle cases that are permitted/not permitted to perform IO, calling in turn: http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXml/EntityHelpers.hs http://www.ninebynine.org/Software/HaskellUtils/HaXml-1.12/src/Text/XML/HaXml/ExtEntity.cpphs #g -- At 15:17 20/01/05 -0500, Mark Carroll wrote: I tried writing a little command-line utility to find the relative path of one thing from another thing (with Unix-like systems in mind). For example, At 14:53 21/01/05 +, John Goerzen wrote: I've been playing with HaXmL lately. I've had a need to convert one XML document to another, and HaXmL was very nice for that. Along the way, I've discovered that I need to do some I/O as part of the conversion (specifically due to timezone-related calculations). Much of HaXML is based around the CFilter type: type CFilter = Content -> [Content] That is, most of the stuff one does in HaXML is a function with that type. Try as I might, I could not figure out a nice way to integrate I/O into this system. A simple IO CFilter wouldn't work, since there has to be input available when it runs. Content -> IO [Content] didn't work either, since the IO ripples up all the way to the top, messing up the nice code everywhere. I finally resorted to unsafePerformIO to get it done. But I'd like to know the proper solution. I do hope that this is not it :-) Thanks, John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Hugs for Zaurus
At 20:15 21/01/05 +, John Goerzen wrote: Hello, I have built a fixed Hugs for the Zaurus PDA running the OpenZaurus distribution. Download here: http://quux.org/devel/zaurus/hugs_hugs98-Nov2003-r1_arm.ipk Cool! I've often thought Haskell should be a good language for programming PDA functions, as a kind of super-calculator. Now I've seen versions mentioned for two PDAs, but no Palm yet. #g Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] weird behavior using HUnit
> > GHC's memory profiling? > > I just gave it a try: when compiled with -prof -auto-all, my program > is memory hungry in both cases, so I cannot really compare... [cc'd back to list in case anyone else finds this useful; hope that's OK] Ah. The cost-centre annotations get in the way of the optimiser, preventing certain optimisations from being performed. It's possible that the new entry point you introduce with testParseLog is similarly preventing something from being inlined. The way to tell (sadly!) is to look at the intermediate code being generated by GHC. In fact there are several intermediate codes to look at. Most of the optimisation work is done while the program is in a form called "Core"; if you look at the result of the optimiser (sometimes called the "simplifier", confusingly) just before this Core is translated to STG you will get the most readable and useful information. http://www.haskell.org/ghc/docs/latest/html/users_guide/options-debugging.html#DUMPING-OUTPUT tells you how, and also explains how to read the output. -ddump-simpl is probably what you want, but it's a while since I've had a look - I could be wrong. Compare what you get with and without that HUnit line that's causing trouble, and see how the critical function is affected. HTH. --KW 8-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: what is inverse of mzero and return?
In article <[EMAIL PROTECTED]>, Keean Schupke <[EMAIL PROTECTED]> wrote: > Right, but we are dealing with the type system here. Remember Haskell > monoids are functors on types, not on values ... (ie the base objects the > 'category theory' is applied to are the types not the values)... > > Therefore we only consider the types when considering Monads. If you remember your category theory, you'll recall that two morphisms are not necessarily the same just because they're between the same two objects. For instance, the objects may be sets, and the morphisms may be functions between sets: morphisms from A to B are the same only if they map each element in A to the same element in B. -- Ashley Yakeley, Seattle WA ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
On 24 Jan 2005, at 10:32, Keean Schupke wrote: Right, but we are dealing with the type system here. Remember Haskell monoids are functors on types, not on values ... (ie the base objects the 'category theory' is applied to are the types not the values)... Therefore we only consider the types when considering Monads. This is not true. Here are the three monad laws as written on the nomaware site: 1. (return x) >>= f == f x 2. m >>= return == m 3. (m >>= f) >>= g == m >>= (\x -> f x >>= g) Taking rule 1, we do not simply mean that return x >>= f and f x have the same type. (This is obviously true). We require that they are equal as values of the type m a. In the case of IO, this means that they perform the same action before yielding the same result. Example: return "hello" >>= putStrLn this does not only have the same type as putStrLn "hello", and return the same value (), but it also carries out exactly the same actions. If it was simply enough that it have the same type, then it would be 'good enough' if return "hello" >>= putStrLn had the same effect as putStrLn "goodbye" ...which has the same type, and the same return value. Aside: you said a couple of messages ago: Yes it is, side effects are quite clearly not counted. The value of (putStrLn "Hello" >> mzero") is mzero. This concept of 'value' only makes sense in some monads. In the List monad there can be many 'values' of a computation. It just happens that IO 'returns' a 'single value' all the time. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Ashley Yakeley wrote: I don't believe this represents a good understanding of IO actions as Haskell values. For instance, 'return ()' and 'putStrLn "Hello"' are the same type, but are clearly different actions and so are usually considered to be different values. That the latter prints out text might be better considered not so much a "side effect" as the actual action itself. You've introduced the concept of "the value of" an IO action, apparently as something separated from "side effects". I don't believe you can properly define this. For instance, what is the "value" of getChar such that it doesn't involve "side effects"? Right, but we are dealing with the type system here. Remember Haskell monoids are functors on types, not on values ... (ie the base objects the 'category theory' is applied to are the types not the values)... Therefore we only consider the types when considering Monads. As such if you wished to consider the examples you gave distinct, the type system would need to distinguish side effects... this can be done with a linear-aliasing type system, but not Haskell's as far as I know... Maybe you could write such types: {putStrLn "Hello"; mzero} :: IO (PutStrLn "Hello" => ()) ??? But if we look at the type of the Functor: fmap :: (a -> b) -> m a -> m b Where is the IO action? Keean. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: what is inverse of mzero and return?
In article <[EMAIL PROTECTED]>, Keean Schupke <[EMAIL PROTECTED]> wrote: > Yes it is, side effects are quite clearly not counted. The value > of (putStrLn "Hello" >> mzero") is mzero. I don't believe this represents a good understanding of IO actions as Haskell values. For instance, 'return ()' and 'putStrLn "Hello"' are the same type, but are clearly different actions and so are usually considered to be different values. That the latter prints out text might be better considered not so much a "side effect" as the actual action itself. You've introduced the concept of "the value of" an IO action, apparently as something separated from "side effects". I don't believe you can properly define this. For instance, what is the "value" of getChar such that it doesn't involve "side effects"? -- Ashley Yakeley, Seattle WA ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Just thinking about this, a monad is a Functor plus two natural-tranformations, Unit and Join. Is there an equivalent definition for MonadPlus... I am not sure I understand where MonadPlus comes from? Is it just a Functor and two different definitions of Unit and Join (from those chosen to be in the class Monad?) Keean. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
On 24 Jan 2005, at 09:36, Keean Schupke wrote: Ashley Yakeley wrote: I disagree. Clearly (putStrLn "Hello" >> mzero) is not the same as mzero. Yes it is, side effects are quite clearly not counted. The value of (putStrLn "Hello" >> mzero") is mzero. This makes no sense to me at all. putStrLn "Hello" has type IO (). mzero (could) have type IO (). But they certainly do not denote the same element of IO ()! Monad/MonadPlus laws surely apply to the full monadic type m a, not just the value type a? Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: what is inverse of mzero and return?
Ashley Yakeley wrote: I disagree. Clearly (putStrLn "Hello" >> mzero) is not the same as mzero. Yes it is, side effects are quite clearly not counted. The value of (putStrLn "Hello" >> mzero") is mzero. In reference to the idea of splitting MonadPlus, what category would you be operating in, if you have a zero but no co-product operation? Keean. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: File path programme
Marcin 'Qrczak' Kowalczyk wrote: These rules agree on "foo", "foo." and "foo.tar.gz", yet disagree on "foo.bar."; I don't know which is more natural. Filename extensions come from DOS 8.3 format. In these kind of names only one '.' is allowed. Unix does not have filename extensions, as '.' is just a normal filename character (with the exception of '.', '..', and filenames starting with a '.' which are hidden files). As far as I know unix utilities like gzip look for specific extensions like '.gz', so it would make more sense on a unix platform to just look for a filename ending '.gz'... this applies recursively so: fred.tar.gz Is a tarred gzip file, so first ending is '.gz' the next is '.tar'... So as far as unix is concerned: "foo.bar." is just as it is... as would any other combination unless the extension matches that specifically used by your application... So the most sensible approach would be to have a list of known extensions which can be recursively applied to the filenames, and leave any other filenames alone. [".gz",".tar",".zip"] ... In other words just splitting on a '.' seems the wrong operation. (Imagine gziping a file called "a..." you get "agz", in other words simply an appended ".gz") Keean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe