Re: [Haskell-cafe] Avoiding parametric function binding
On Sat, Dec 31, 2011 at 4:09 PM, Kevin Quick qu...@sparq.org wrote: onVarElem :: forall a . (Show a) = (Maybe a - String) - Var - String onVarElem f (V1 x) = f x onVarElem f (V2 x) = f x main = putStrLn . onVarElem elemStr $ test This is probably a better design, but still fails for the same reason: Couldn't match expected type `Int' with actual type `[Char]' Expected type: Maybe Int Actual type: Maybe String In the first argument of `f', namely `x' In the expression: f x The problem is the scope of the quantification of the type variable 'a'. You can use higher-rank types (via the Rnak2Types or RankNTypes language extension) to achieve what you want. Change the type of 'onVarElem' to onVarElem :: (forall a . (Show a) = Maybe a - String) - Var - String In contrast to the previous type, this type says that the provided function must be polymorphic over Show instances 'a', while the previous type would have allowed any specialization of 'a' with a Show instance. With the previous type, the call onVarElem (maybe show (show . not)) would have been legal, with the new type it is not, which is necessary for the implementation to be well typed. If you don't want to use a language extension that allows you to require polymorphism on function arguments, then Stephen's solution is a good workaround. Sebastian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Thanks and a happy new year!
Dear fellow Haskellers, as I have learned so much throughout the past four years of Haskell experience, I feel obligated to thank everyone for the nice support and the great ideas. Exploring and using Haskell has changed my way of thinking about programming and computers in a profound way and made me a lot more productive. A happy new year 2012 for Haskell hacking to everyone! Many greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife = sex) http://ertes.de/ signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] On the purity of Haskell
Chris Smith cdsm...@gmail.com writes: I wonder: can writing to memory be called a “computational effect”? If yes, then every computation is impure. I wonder if not the important bit is that pure computations are unaffected by other computations (and not whether they can affect other computations). Many pure computations have side effects (increases temperature, modifies hardware registers and memory, etc), but their effect can only be observed in IO. (E.g. Debug.Trace.trace provides a non-IO interface by use of unsafePerformIO which is often considered cheating, but in this view it really is pure.) -k -- 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] On the purity of Haskell
On Sun, Jan 1, 2012 at 3:26 PM, Ketil Malde ke...@malde.org wrote: Chris Smith cdsm...@gmail.com writes: I wonder: can writing to memory be called a “computational effect”? If yes, then every computation is impure. I wonder if not the important bit is that pure computations are unaffected by other computations (and not whether they can affect other computations). Many pure computations have side effects (increases temperature, modifies hardware registers and memory, etc), but their effect can only be observed in IO. (E.g. Debug.Trace.trace provides a non-IO interface by use of unsafePerformIO which is often considered cheating, but in this view it really is pure.) The point of purity (and related concepts) is to have useful tools for working with and reasoning about your code. Lambda calculi can be seen as the prototypical functional languages, and the standard ones have the following nice property: The only difference between reduction strategies is termination. Non-strict strategies will terminate for more expressions than strict ones, but that is the only difference. This property is often taken to be the nub of what it means to be a pure functional language. If the language is an extension of the lambda calculus that preserves this property, then it is a pure functional language. Haskell with the 'unsafe' stuff removed is such a language by this definition, and most GHC additions are too, depending on how you want to argue. It is even true with respect to the output of programs, but not when you're using Debug.Trace, because: flip (+) (foo `trace` 1) (bar `trace` 1) will print different things with different evaluation orders. A similar property is referential transparency, which allows you to factor your program however you want without changing its denotation. So: (\x - x + x) e is the same as: e + e This actually fails for strict evaluation strategies unless you relax it to be 'same denotation up to bottoms' or some such. But not having to worry about whether you're changing the definedness of your programs by factoring/inlining is actually a useful property that strict languages lack. Also, the embedded IO language does not have this property. do x - m ; f x x is different from do x - m ; y - m ; f x y and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. But the embedded IO language lacking this property should not be confused with Haskell lacking this property. Anyhow, here's my point: these properties can be grounded in useful features of the language. However, for the vast majority of people, being able to factor their code differently and have it appear exactly the same to someone with a memory sniffer isn't useful. And unless you're doing serious crypto or something, there is no correct amount of heat for a program to produce. So if we're wondering about whether we should define purity or referential transparency to incorporate these things, the answer is an easy, no. We throw out the possibility that 'e + e' may do more work than '(\x - x + x) e' for the same reason (indeed, we often want to factor it so that it performs better, while still being confident that it is in some sense the same program, despite the fact that performing better might by some definitions mean that it isn't the same program). But the stuff that shows up on stdout/stderr typically is something we care about, so it's sensible to include that. If you don't care what happens there, go ahead and use Debug.Trace. It's pure/referentially transparent modulo stuff you don't care about. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] On the purity of Haskell
Dan Doel : ... Also, the embedded IO language does not have this property. do x- m ; f x x is different from do x- m ; y- m ; f x y and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. Sorry, what are you trying to suggest? You show two OBVIOUSLY different pieces of code, and you say that they are different. If, by chance, some newbie reads that and gets the impression that (-) is something equivalent to (=), you are serving the devil. Jerzy Karczmarczuk ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] On the purity of Haskell
Le Sun, 1 Jan 2012 16:31:51 -0500, Dan Doel dan.d...@gmail.com a écrit : On Sun, Jan 1, 2012 at 3:26 PM, Ketil Malde ke...@malde.org wrote: Chris Smith cdsm...@gmail.com writes: I wonder: can writing to memory be called a “computational effect”? If yes, then every computation is impure. I wonder if not the important bit is that pure computations are unaffected by other computations (and not whether they can affect other computations). Many pure computations have side effects (increases temperature, modifies hardware registers and memory, etc), but their effect can only be observed in IO. (E.g. Debug.Trace.trace provides a non-IO interface by use of unsafePerformIO which is often considered cheating, but in this view it really is pure.) The point of purity (and related concepts) is to have useful tools for working with and reasoning about your code. Lambda calculi can be seen as the prototypical functional languages, and the standard ones have the following nice property: The only difference between reduction strategies is termination. Non-strict strategies will terminate for more expressions than strict ones, but that is the only difference. This has nothing to do with purity (purity and strictness/lazyness are different). This property is often taken to be the nub of what it means to be a pure functional language. If the language is an extension of the lambda calculus that preserves this property, then it is a pure functional language. Haskell with the 'unsafe' stuff removed is such a language by this definition, and most GHC additions are too, depending on how you want to argue. It is even true with respect to the output of programs, but not when you're using Debug.Trace, because: flip (+) (foo `trace` 1) (bar `trace` 1) will print different things with different evaluation orders. A similar property is referential transparency, which allows you to factor your program however you want without changing its denotation. So: (\x - x + x) e is the same as: e + e That is not really what I call referential transparency; for me this is rather β reduction… For me, referential transparency means that the same two closed expression in one context denote the same value. So that is rather: let x = e y = e in x + y is the same as: e + e This actually fails for strict evaluation strategies unless you relax it to be 'same denotation up to bottoms' or some such. But not having to worry about whether you're changing the definedness of your programs by factoring/inlining is actually a useful property that strict languages lack. In fact, strict language can be referentially transparent; it is the case in ML (in fact I only know of Ocaml minus impure features, but well…). Also, the embedded IO language does not have this property. do x - m ; f x x is different from do x - m ; y - m ; f x y In fact IO IS referentially transparent; do NOT FORGET that there is some syntactic sugar: do x - m ; f x x = (=) m (\x - f x x) do x - m ; y - m ; f x y = (=) m (\x - (=) m (\y - f x y)) So when we desugar it (and it is only desugaring, it is no optimization/reduction/whatEverElseYouWant; these two expressions have the same AST once parsed), where would you want to put referential transparency? and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. But the embedded IO language lacking this property should not be confused with Haskell lacking this property. It is not an embedded IO language, it is just some sugar for monads; you can as well do: maybePlus :: (Mabe Int) - (Maybe Int) - Maybe Int maybePlus mx my = do x - mx y - my return $ x+y and there is absolutely no IO. Anyhow, here's my point: these properties can be grounded in useful features of the language. However, for the vast majority of people, being able to factor their code differently and have it appear exactly the same to someone with a memory sniffer isn't useful. And unless you're doing serious crypto or something, there is no correct amount of heat for a program to produce. So if we're wondering about whether we should define purity or referential transparency to incorporate these things, the answer is an easy, no. We throw out the possibility that 'e + e' may do more work than '(\x - x + x) e' for the same reason (indeed, we often want to factor it so that it performs better, while still being confident that it is in some sense the same program, despite the fact that performing better might by some definitions mean that it isn't the same program). But the stuff that shows up on stdout/stderr typically is something we care about, so it's sensible to include that. If you don't care what happens there, go ahead and use Debug.Trace. It's pure/referentially transparent modulo stuff you don't
Re: [Haskell-cafe] On the purity of Haskell
This thread pretty much exemplifies why many people don't bother with this mailing list anymore. On Sun, Jan 1, 2012 at 7:00 PM, AUGER Cédric sedri...@gmail.com wrote: Le Sun, 1 Jan 2012 16:31:51 -0500, Dan Doel dan.d...@gmail.com a écrit : On Sun, Jan 1, 2012 at 3:26 PM, Ketil Malde ke...@malde.org wrote: Chris Smith cdsm...@gmail.com writes: I wonder: can writing to memory be called a “computational effect”? If yes, then every computation is impure. I wonder if not the important bit is that pure computations are unaffected by other computations (and not whether they can affect other computations). Many pure computations have side effects (increases temperature, modifies hardware registers and memory, etc), but their effect can only be observed in IO. (E.g. Debug.Trace.trace provides a non-IO interface by use of unsafePerformIO which is often considered cheating, but in this view it really is pure.) The point of purity (and related concepts) is to have useful tools for working with and reasoning about your code. Lambda calculi can be seen as the prototypical functional languages, and the standard ones have the following nice property: The only difference between reduction strategies is termination. Non-strict strategies will terminate for more expressions than strict ones, but that is the only difference. This has nothing to do with purity (purity and strictness/lazyness are different). This property is often taken to be the nub of what it means to be a pure functional language. If the language is an extension of the lambda calculus that preserves this property, then it is a pure functional language. Haskell with the 'unsafe' stuff removed is such a language by this definition, and most GHC additions are too, depending on how you want to argue. It is even true with respect to the output of programs, but not when you're using Debug.Trace, because: flip (+) (foo `trace` 1) (bar `trace` 1) will print different things with different evaluation orders. A similar property is referential transparency, which allows you to factor your program however you want without changing its denotation. So: (\x - x + x) e is the same as: e + e That is not really what I call referential transparency; for me this is rather β reduction… For me, referential transparency means that the same two closed expression in one context denote the same value. So that is rather: let x = e y = e in x + y is the same as: e + e This actually fails for strict evaluation strategies unless you relax it to be 'same denotation up to bottoms' or some such. But not having to worry about whether you're changing the definedness of your programs by factoring/inlining is actually a useful property that strict languages lack. In fact, strict language can be referentially transparent; it is the case in ML (in fact I only know of Ocaml minus impure features, but well…). Also, the embedded IO language does not have this property. do x - m ; f x x is different from do x - m ; y - m ; f x y In fact IO IS referentially transparent; do NOT FORGET that there is some syntactic sugar: do x - m ; f x x = (=) m (\x - f x x) do x - m ; y - m ; f x y = (=) m (\x - (=) m (\y - f x y)) So when we desugar it (and it is only desugaring, it is no optimization/reduction/whatEverElseYouWant; these two expressions have the same AST once parsed), where would you want to put referential transparency? and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. But the embedded IO language lacking this property should not be confused with Haskell lacking this property. It is not an embedded IO language, it is just some sugar for monads; you can as well do: maybePlus :: (Mabe Int) - (Maybe Int) - Maybe Int maybePlus mx my = do x - mx y - my return $ x+y and there is absolutely no IO. Anyhow, here's my point: these properties can be grounded in useful features of the language. However, for the vast majority of people, being able to factor their code differently and have it appear exactly the same to someone with a memory sniffer isn't useful. And unless you're doing serious crypto or something, there is no correct amount of heat for a program to produce. So if we're wondering about whether we should define purity or referential transparency to incorporate these things, the answer is an easy, no. We throw out the possibility that 'e + e' may do more work than '(\x - x + x) e' for the same reason (indeed, we often want to factor it so that it performs better, while still being confident that it is in some sense the same program, despite the fact that performing better might by some definitions mean that it isn't the
[Haskell-cafe] Installing glib
I have the Haskell Platform (version 7.0.4 of ghc) installed on my macbook (OS X 10.7 Lion) and I'd like to install glib. However, when I try cabal install glib, I get: cabal install glib Resolving dependencies... [1 of 2] Compiling SetupWrapper ( /tmp/glib-0.12.25777/glib-0.12.2/SetupWrapper.hs, /tmp/glib-0.12.25777/glib-0.12.2/dist/setup/SetupWrapper.o ) [2 of 2] Compiling Main ( /tmp/glib-0.12.25777/glib-0.12.2/Setup.hs, /tmp/glib-0.12.25777/glib-0.12.2/dist/setup/Main.o ) Linking /tmp/glib-0.12.25777/glib-0.12.2/dist/setup/setup ... ld: warning: could not create compact unwind for _ffi_call_unix64: does not use RBP or RSP based frame [1 of 2] Compiling Gtk2HsSetup ( Gtk2HsSetup.hs, dist/setup-wrapper/Gtk2HsSetup.o ) [2 of 2] Compiling Main ( SetupMain.hs, dist/setup-wrapper/Main.o ) Linking dist/setup-wrapper/setup ... ld: warning: could not create compact unwind for _ffi_call_unix64: does not use RBP or RSP based frame Cannot find gtk2hsC2hs Please install `gtk2hs-buildtools` first and check that the install directory is in your PATH (e.g. HOME/.cabal/bin). cabal: Error: some packages failed to install: glib-0.12.2 failed during the configure step. The exception was: ExitFailure 1 --- I've tried cabal install gtk2hs-buildtools, and appears to complete (it does have two compilation warnings), but that doesn't help. Any suggestions? Victor Miller Here's the result cabal install gtk2hs-buildtools: bash-3.2$ sudo cabal install gtk2hs-buildtools Resolving dependencies... Configuring gtk2hs-buildtools-0.12.1... Preprocessing executables for gtk2hs-buildtools-0.12.1... Building gtk2hs-buildtools-0.12.1... [1 of 2] Compiling Paths_gtk2hs_buildtools ( dist/build/autogen/Paths_gtk2hs_buildtools.hs, dist/build/gtk2hsTypeGen/gtk2hsTypeGen-tmp/Paths_gtk2hs_buildtools.o ) [2 of 2] Compiling Main ( hierarchyGen/TypeGen.hs, dist/build/gtk2hsTypeGen/gtk2hsTypeGen-tmp/Main.o ) Linking dist/build/gtk2hsTypeGen/gtk2hsTypeGen ... ld: warning: could not create compact unwind for _ffi_call_unix64: does not use RBP or RSP based frame [1 of 2] Compiling Paths_gtk2hs_buildtools ( dist/build/autogen/Paths_gtk2hs_buildtools.hs, dist/build/gtk2hsHookGenerator/gtk2hsHookGenerator-tmp/Paths_gtk2hs_buildtools.o ) [2 of 2] Compiling Main ( callbackGen/HookGenerator.hs, dist/build/gtk2hsHookGenerator/gtk2hsHookGenerator-tmp/Main.o ) Linking dist/build/gtk2hsHookGenerator/gtk2hsHookGenerator ... ld: warning: could not create compact unwind for _ffi_call_unix64: does not use RBP or RSP based frame [ 1 of 41] Compiling DLists ( c2hs/base/general/DLists.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/DLists.o ) dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/CLexer.hs:1:12: Warning: -fglasgow-exts is deprecated: Use individual extensions instead [ 2 of 41] Compiling BaseVersion ( c2hs/base/admin/BaseVersion.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/BaseVersion.o ) [ 3 of 41] Compiling Switches ( c2hs/state/Switches.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Switches.o ) [ 4 of 41] Compiling Map ( c2hs/base/general/Map.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Map.o ) [ 5 of 41] Compiling FastMutInt ( c2hs/base/general/FastMutInt.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/FastMutInt.o ) [ 6 of 41] Compiling Config ( c2hs/base/admin/Config.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Config.o ) [ 7 of 41] Compiling C2HSConfig ( c2hs/toplevel/C2HSConfig.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/C2HSConfig.o ) [ 8 of 41] Compiling CInfo( c2hs/gen/CInfo.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/CInfo.o ) [ 9 of 41] Compiling Version ( c2hs/toplevel/Version.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Version.o ) [10 of 41] Compiling Binary ( c2hs/base/general/Binary.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Binary.o ) [11 of 41] Compiling Position ( c2hs/base/general/Position.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Position.o ) [12 of 41] Compiling UNames ( c2hs/base/general/UNames.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/UNames.o ) [13 of 41] Compiling Errors ( c2hs/base/errors/Errors.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Errors.o ) [14 of 41] Compiling Attributes ( c2hs/base/syms/Attributes.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Attributes.o ) [15 of 41] Compiling Idents ( c2hs/base/syms/Idents.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Idents.o ) [16 of 41] Compiling CTokens ( c2hs/c/CTokens.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/CTokens.o ) [17 of 41] Compiling CAST ( c2hs/c/CAST.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/CAST.o ) [18 of 41] Compiling CPretty ( c2hs/c/CPretty.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/CPretty.o ) [19 of 41] Compiling Lexers ( c2hs/base/syntax/Lexers.hs, dist/build/gtk2hsC2hs/gtk2hsC2hs-tmp/Lexers.o ) [20 of 41] Compiling StateTrans ( c2hs/base/state/StateTrans.hs,
Re: [Haskell-cafe] Installing glib
On Sun, Jan 1, 2012 at 21:49, Victor Miller victorsmil...@gmail.com wrote: Cannot find gtk2hsC2hs Please install `gtk2hs-buildtools` first and check that the install directory is in your PATH (e.g. HOME/.cabal/bin). The message there is incorrect for Mac OS X; cabal installs executables somewhere under ~/Library/Haskell, and (inconsistently and incoherently) sometimes in per-package bin directories under that. This is a PITA that I don't know how to work around properly (just setting the bin directory ~/.cabal/config still seems to keep the occasional per-package bin directory silliness). Expect to have to find ~/Library/Haskell -name bin -type d periodically to figure out where cabal put stuff, and symlink it all to ~/bin or whatever. :/ -- brandon s allbery allber...@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] On the purity of Haskell
On 01/01/2012 22:57, Jerzy Karczmarczuk wrote: Dan Doel : ... Also, the embedded IO language does not have this property. do x- m ; f x x is different from do x- m ; y- m ; f x y and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. Sorry, what are you trying to suggest? You show two OBVIOUSLY different pieces of code, and you say that they are different. If, by chance, some newbie reads that and gets the impression that (-) is something equivalent to (=), you are serving the devil. Speaking as the devil... The do-notation sugar may confuse the issue - the - looks like an operator, but translating to binds-and-lambdas form suggests otherwise. Quick translations (I hope no mistakes) with lots of parens... m = (\x - (f x x)) m = (\x - (m = (\y - (f x y At first sight, these two expressions can give different results for reasons other than evaluation order. In particular, there are two bind operators, not just one. That is, x and y could get different values for reasons other than the two m references referring to different things. So... is that true? Of course even the bind operator arguably isn't primitive. We could translate to get rid of those too, and see what lies underneath. This is where we start seeing functions of type... World - (x, World) Problem - this level of abstraction is hypothetical. It is not part of the Haskell language. Haskell specifically defines the IO monad to be a black box. I look at this World parameter as purely hypothetical, a trick used to gain an intuition. Whereas Jerzy (I think) uses it to claim Haskell is referentially transparent - those differing x and y values come from different worlds, or different world-states. I'm not entirely sure, though, as we got sidetracked. If main returns a function of type World - (x, World) wrapped in a monad context, then there is referential transparency as defined in computer science. But is that a fair claim? In this model, Haskell is an interpreted language for compositing functions. We can call those functions programs. The executable is a translation of the function returned by main, but *not* a translation of the source code. But GHC is called a compiler, and compilation is usually considered a kind of translation - the executable is a translation of the source code. GHCi is an interpreter, but it doesn't stop at returning a function of type World - (x, World) - it does the I/O. And the reason we use these terms is because, as programmers, we think of the executable as the program - as a translation of the source code. So what main returns - that hypothetical function World - (x, World) - isn't just a product of the program, it's also a representation of the program. I've made similar points before, but how do they work out this time... So... when evaluate what effects referentially transparent - --- - compile-time main no yes run-time main someParticularWorld yes yes(?) I've proved effects at run-time, but in this model, the intermediate and final world-states are products of the evaluation of that main someParticularWorld expression. Even the results extracted from input actions are referentially transparent - or if not, we're dealing with the philosophy of determinism. It's probable that Jerzy told me this earlier and I wasn't ready to hear it then. However - we can say basically the same things about C. The World parameter is implicit in C but then it's implicit in Haskell too. Everything inside the IO monad black box is outside the scope of the Haskell language except in that semantics are defined for the primitive IO actions - basically what happens when a result is extracted out as part of evaluating a bind. That (?) in the yes(?) is because this is all contingent on that hypothetical World - (x, World) function hidden inside the IO monad context, which is not specified in the Haskell language. When I say that Haskell lacks referential transparency because the execution of primitive IO actions is tied to the evaluation of the bind operators that extract out their results, and different executions of the same action yield different results, I'm only appealing to the defined semantics of the Haskell language. I'm not appealing to a hypothetical model where the world is passed as a parameter. OTOH, this World - (x, World) model is much more appealing than my partially-evaluated-functions-as-AST-nodes model. So - the issue seems to be whether the IO monad is a context holding world-manipulating functions, or whether it's a black box with semantics specified at the bind level. And if referential transparency is decided at this level, what practical relevance does it have? It's probably better to
Re: [Haskell-cafe] Composing Enumeratees in enumerator
I wound up emailing John Millikin about this and he made a good case against these kinds of simplified operators, which is basically the problem of handling left-over input. The joinI and joinE combinators discard the left-over Stream that is yielded by the inner iteratee. (As John explains it, this is a trade-off between ease of use and programming complexity.) Simplified operators (like $=, =$, and now =$=) use repeated joinI's, so left-over input may be lost in various places. When using simple iteratees that never yield left-over input, this isn't a problem and the operators make sense. For more complex pipelines, John advocates a style like this: joinI (foo $$ (bar $$ baz)) so that left over data is only discarded once after the computation is otherwise complete. In any case, there's now a new release of enumerator (0.4.17) which includes an enumeratee composition operator: (=$=) :: Monad m = Enumeratee a1 a2 m (Step a3 m b) - Enumeratee a2 a3 m b - Enumeratee a1 a3 m b. Cheers, Mike Craig On Tue, Dec 27, 2011 at 10:12 AM, Michael Craig mks...@gmail.com wrote: Thanks for the replies, all. It's good to see that the other iteratee packages out there are addressing this issue. I still don't get why it's an issue in the first place. It seems to me like a pretty simple thing to implement: (=$=) :: (Monad m) = Enumeratee a0 a1 m (Step a2 m b) - Enumeratee a1 a2 m b - Enumeratee a0 a2 m b (=$=) e01 e12 step = Iteratee $ do step' - runIteratee $ e12 step runIteratee . joinI $ e01 step' This puts a type restriction on the LHS enumeratee, but enumeratees are generally polymorphic in the last type param anyway. (And joinE has a similar restriction when composing an enumerator with an enumeratee.) Is there a good reason why enumerator doesn't export this or something analogous? Mike Craig On Sun, Dec 25, 2011 at 10:20 PM, Conrad Parker con...@metadecks.orgwrote: On 24 December 2011 05:47, Michael Craig mks...@gmail.com wrote: I've been looking for a way to compose enumeratees in the enumerator package, but I've come up with nothing so far. I want this function (=$=) :: Monad m = Enumeratee a0 a1 m b - Enumeratee a1 a2 m b - Enumeratee a0 a2 m b I'm building a modular library on top of enumerator that facilitates reading time series data from a DB, applying any number of transformations to it, and then writing it back / doing something else with it. I'd like to be able to write simple transformations (enumeratees) and compose them without binding them to either a db reader (enumerator) or db writer (iteratee). I've been looking at the iterIO package as a possible alternative, because it seems to allow easy composition of Inums (enumeratees). I'm a little skittish of it because it seems unpopular next to enumerator. Hi Michael, You could also look at the iteratee package. This is the signature of the () operator: () :: (Nullable s1, Monad m) = (forall x. Enumeratee s1 s2 m x) - Enumeratee s2 s3 m a - Enumeratee s1 s3 m a it's quite useful for composing enumeratees, likewise its friend () swims the other way. http://hackage.haskell.org/packages/archive/iteratee/0.8.7.5/doc/html/Data-Iteratee-Iteratee.html cheers, Conrad. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] On the purity of Haskell
... World - (x, World) ... I look at this World parameter as purely hypothetical, a trick used to gain an intuition. Whereas Jerzy (I think) uses it to claim Haskell is referentially transparent - those differing x and y values come from different worlds, or different world-states. I don't see this interpretation in Jerzy's words, and I'd be very surprised if he had that sort of argument in mind. If main returns a function of type World - (x, World) wrapped in ... Main does not return or denote such a thing. The idea that Haskell IO can be accurately explained as (i.e., denotes) World - (x,World) is a persistent myth. That model cannot explain concurrency (even with the outside world) or nondeterminism, both of which are part of Haskell IO. We don't have an precise accurate denotational model for IO, in contrast to most other types in Haskell. Which is to say that while much of Haskell programming is denotative, IO programming is not. Peter Landin, an important figure in functional programming, proposed and defined this term denotative as a substantive precise replacement for the fuzzier notions of functional and declarative. He offered his definition and suggested that When faced with a new notation that borrows the functional appearance of everyday algebra, it is (c) that gives us a test for whether the notation is genuinely functional or merely masquerading. Of course, various subsets of IO can be precisely and accurately modeled, but so far not IO as we use it. It's very unlikely that we ever will have such a (precise accurate) model, and by design, as explained at http://conal.net/blog/posts/notions-of-purity-in-haskell/#comment-22829 . - Conal On Sun, Jan 1, 2012 at 7:43 PM, Steve Horne sh006d3...@blueyonder.co.ukwrote: On 01/01/2012 22:57, Jerzy Karczmarczuk wrote: Dan Doel : ... Also, the embedded IO language does not have this property. do x- m ; f x x is different from do x- m ; y- m ; f x y and so on. This is why you shouldn't write your whole program with IO functions; it lacks nice properties for working with your code. Sorry, what are you trying to suggest? You show two OBVIOUSLY different pieces of code, and you say that they are different. If, by chance, some newbie reads that and gets the impression that (-) is something equivalent to (=), you are serving the devil. Speaking as the devil... The do-notation sugar may confuse the issue - the - looks like an operator, but translating to binds-and-lambdas form suggests otherwise. Quick translations (I hope no mistakes) with lots of parens... m = (\x - (f x x)) m = (\x - (m = (\y - (f x y At first sight, these two expressions can give different results for reasons other than evaluation order. In particular, there are two bind operators, not just one. That is, x and y could get different values for reasons other than the two m references referring to different things. So... is that true? Of course even the bind operator arguably isn't primitive. We could translate to get rid of those too, and see what lies underneath. This is where we start seeing functions of type... World - (x, World) Problem - this level of abstraction is hypothetical. It is not part of the Haskell language. Haskell specifically defines the IO monad to be a black box. I look at this World parameter as purely hypothetical, a trick used to gain an intuition. Whereas Jerzy (I think) uses it to claim Haskell is referentially transparent - those differing x and y values come from different worlds, or different world-states. I'm not entirely sure, though, as we got sidetracked. If main returns a function of type World - (x, World) wrapped in a monad context, then there is referential transparency as defined in computer science. But is that a fair claim? In this model, Haskell is an interpreted language for compositing functions. We can call those functions programs. The executable is a translation of the function returned by main, but *not* a translation of the source code. But GHC is called a compiler, and compilation is usually considered a kind of translation - the executable is a translation of the source code. GHCi is an interpreter, but it doesn't stop at returning a function of type World - (x, World) - it does the I/O. And the reason we use these terms is because, as programmers, we think of the executable as the program - as a translation of the source code. So what main returns - that hypothetical function World - (x, World) - isn't just a product of the program, it's also a representation of the program. I've made similar points before, but how do they work out this time... So... when evaluate what effects referentially transparent - --- - compile-time main no yes run-time main someParticularWorld yes yes(?) I've
Re: [Haskell-cafe] On the purity of Haskell
Steve Horne sh006d3...@blueyonder.co.uk wrote: The do-notation sugar may confuse the issue - the - looks like an operator, but translating to binds-and-lambdas form suggests otherwise. Quick translations (I hope no mistakes) with lots of parens... m = (\x - (f x x)) m = (\x - (m = (\y - (f x y First of all, you can omit all parentheses, because the (=) operator is associative by definition (this is not checked by the compiler though). At first sight, these two expressions can give different results for reasons other than evaluation order. In particular, there are two bind operators, not just one. That is, x and y could get different values for reasons other than the two m references referring to different things. So... is that true? Yes, that's correct. Remember that referential transparency does not say that you are not allowed to pass different values to the same function. It just forbids functions to return different results for different inputs, and this is true for both expressions you showed. Using a state monad to get more concrete, let's say that 'm' returns the current state and then increments it. If the start state is 3, then 'x' will become 3 on execution and 'y' will become 4. However, the result of the composition is /always/ the state computation that returns the result of 'f' applied to the current state and the incremented current state. Just like when you write x = getLine, then you can safely replace any occurence of 'getLine' by 'x'. Of course even the bind operator arguably isn't primitive. We could translate to get rid of those too, and see what lies underneath. This is where we start seeing functions of type... World - (x, World) Problem - this level of abstraction is hypothetical. It is not part of the Haskell language. Haskell specifically defines the IO monad to be a black box. And that's fine, because IO is an embedded DSL. A better view of IO is a GADT like: data IO :: * - * where GetLine :: IO String PutStrLn :: String - IO () ... This is still hypothetical, but it shows how even IO is easily referentially transparent (as long as you don't use unsafe* cheats). Furthermore you have to consider that /execution/ of IO actions is entirely outside the scope of the language itself. A compiler turns an expression of type IO () into machine code that executes the encoded recipe. In any case, you have to differentiate between evaluation and IO execution. If main returns a function of type World - (x, World) wrapped in a monad context, then there is referential transparency as defined in computer science. But is that a fair claim? Even though the World state monad is a bad intuition in my opinion, why not? Evaluation is referentially transparent, because you don't evaluate to results of IO actions. You evaluate to the IO actions themselves. This is not a hack, it is a great feature, because it's precisely what allows us to build real world actions using combinators. In this model, Haskell is an interpreted language for compositing functions. We can call those functions programs. The executable is a translation of the function returned by main, but *not* a translation of the source code. It is a translation of the source code, because evaluation happens at run-time, interleaved with the execution of 'main', as 'main' goes along forcing thunks (in a thunk-based implementation). So what main returns - that hypothetical function World - (x, World) - isn't just a product of the program, it's also a representation of the program. And there comes the limitation of this intuition. It is so theoretical that you can't express a function of that type even as machine code. On the other hand, the GADT variant could indeed be turned into bytecode and then interpreted by a bytecode machine. But this is not how it works in, say, GHC. GHC compiles to native code using the thunk approach I mentioned earlier. When I say that Haskell lacks referential transparency because the execution of primitive IO actions is tied to the evaluation of the bind operators that extract out their results, and different executions of the same action yield different results, I'm only appealing to the defined semantics of the Haskell language. I'm not appealing to a hypothetical model where the world is passed as a parameter. This is where your mistake is again: execution vs. evaluation. The (=) operator does /not/ extract results. It doesn't have to. It just makes sure (abstractly!) that the second argument is applied to the result of the first argument at execution time. It builds a data dependency between monadic actions. (=) is composition, not execution. Execution is outside the scope of the monadic interface, and for the specific case of IO it's even outside the scope of the language. If you think about it, you will find that (=) can't even extract results. The only thing it can do with results
[Haskell-cafe] Grok Monad Transformers - some help needed
I'm having another go at figuring out Monad Transformers, starting at the same point I've started and stopped the last couple of times. That's this tutorial... http://blog.sigfpe.com/2006/05/grok-haskell-monad-transformers.html Onion layers, lift etc - I get that. But I've never actually got anything to work - and therefore never built the confidence to move on. Problem 1 - this is literate Haskell. I've tried feeding it to haddock - all I get is an error about it lacking a main. I don't know what to actually do with this after putting it in a *.lhs file. No big deal, but... Problem 2 - even cutting the code out, shoving it in a *.hs file, and :loading it into GHCi, I still get a lot of errors. For the functions test1 and test2, the fixes were explicit type signatures. Easy enough to figure out... test1 :: State Int (Int, Int) test2 :: State String (String, String) I guess the basic issue is the same with test3 (and though I haven't tried the others today, probably test5 and test7 too). The trouble there is that I don't know what those type signatures should be because I don't know that much about monad transformers and how they can work. I can see what's going on in the body of test3, but that is a very small amount of understanding - the type signatures are important. And I can't use :type because GHCi is rejecting the code. In short... HELP!!! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Grok Monad Transformers - some help needed
I don't know what to actually do with this after putting it in a *.lhs file. You can :load *.lhs into ghci the same way you load .hs-files. I'm not sure why you were getting the ambiguous type errors. I didn't: test1 :: StateT Integer Identity (Integer, Integer) test2 :: StateT [Char] Identity ([Char], [Char]) test3 :: StateT Integer (StateT [Char] Identity) (Integer, [Char]) test5 :: StateT Integer IO () test7 :: StateT Integer (StateT [Char] Identity) (Integer, [Char]) Hope that helps. Arseniy. On 2 January 2012 06:03, Steve Horne sh006d3...@blueyonder.co.uk wrote: I'm having another go at figuring out Monad Transformers, starting at the same point I've started and stopped the last couple of times. That's this tutorial... http://blog.sigfpe.com/2006/05/grok-haskell-monad-transformers.html Onion layers, lift etc - I get that. But I've never actually got anything to work - and therefore never built the confidence to move on. Problem 1 - this is literate Haskell. I've tried feeding it to haddock - all I get is an error about it lacking a main. I don't know what to actually do with this after putting it in a *.lhs file. No big deal, but... Problem 2 - even cutting the code out, shoving it in a *.hs file, and :loading it into GHCi, I still get a lot of errors. For the functions test1 and test2, the fixes were explicit type signatures. Easy enough to figure out... test1 :: State Int (Int, Int) test2 :: State String (String, String) I guess the basic issue is the same with test3 (and though I haven't tried the others today, probably test5 and test7 too). The trouble there is that I don't know what those type signatures should be because I don't know that much about monad transformers and how they can work. I can see what's going on in the body of test3, but that is a very small amount of understanding - the type signatures are important. And I can't use :type because GHCi is rejecting the code. In short... HELP!!! ___ 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