Experimental IRC log haskell-2009-06-02

Available formats: content-negotiated html turtle (see SIOC for the vocabulary)

Back to channel and daily index: content-negotiated html turtle

These logs are provided as an experiment in indexing discussions using IRCHub.py, Irc2RDF.hs, and SIOC.

00:00:05<Peaker>vininim: well, stop that :)
00:00:36<vininim>but, most of the mutation is inside packedmatrix inplace mutation
00:01:06<Peaker>Haskell performance is indeed a "black art" -- it takes quite a while before understanding the various techniques required to get fast Haskell. So much so that I think I would downplay Haskell performance claims, as they are even misleading. Not "nearly as fast as C", but just "Much faster than Python/et al"
00:01:31<Peaker>it can be nearly as fast as C, for specific programs or if you are a black arts master
00:01:45<Cale>I don't know about it being a black art.
00:02:04<aavogt>doesn't writing the benchmark C take skill too?
00:02:08<vininim>I dont have goats :/
00:02:11<Cale>It's just that lazy evaluation is sufficiently different to strict evaluation that your existing knowledge about how to make strict programs perform well doesn't apply.
00:02:37<Cale>So it's just something that you have to learn.
00:04:51<Peaker>Cale: C encourages programs that perform well by correlating pretty well programs that are fast with programs that are short/easy
00:05:12<Cale>Usually short programs are the fast ones in Haskell too.
00:05:15<vininim>well, even with the overhead it's way better than octave for what I'm doing. =P
00:05:30<Peaker>Cale: Knowing enough C to write correct programs and a bit of CS is enough to get fast-executing C. Knowing enough Haskell to write denotationally correct Haskell programs and a bit of CS is not enough to write fast-performing Haskell programs
00:05:41<Cale>I disagree on that first point.
00:05:58<Peaker>Cale: how come?
00:05:59<Twey>ACTION ponders the possibility of ever knowing enough C to write correct programs
00:06:20<Cale>Because I realise that it actually took me a long time to learn how to write good-performing imperative programs.
00:06:28<Peaker>Twey: if you use a subset of C in very strict ways -- its possible
00:06:32<vininim>it would be better if we just didn't get in the way of the compiler and enhance it =P
00:06:42<Twey>But not Turing-complete :-P
00:06:50<Cale>A number of years at least.
00:06:55<Twey>vininim: *nods*
00:06:56<Peaker>Cale: well, much of CS focuses on well-performing imperative algorithms -- so knowing some CS covers that..
00:07:00<A1kmm>Hi, has anyone here managed to get ghc parallel Haskell to work for them and get a program to speed up? I have even tried writing a very simple, trivially parallelisable test program and parallel Haskell slows it down.
00:07:15<Cale>It took me about the same amount of time to learn how to write programs which perform well in Haskell.
00:07:48<Cale>A1kmm: I don't have a multiprocessor, but I can take a look and see if I can guess at why it's slower.
00:07:57<vininim>I hope it's less than 10 years (perfomance tunning 3 hours per day)
00:08:02<Cale>A1kmm: You might be creating too many sparks.
00:08:03<Peaker>Twey: well, the subset being used is indeed not turing complete most of the time. When you do recurse or loop over things that are difficult to show as simply finite, you are far more careful and use a different subset of C, could say a different language, that is turing complete
00:08:10<A1kmm>Cale: I started with:
00:08:16<A1kmm>import Numeric.GSL.Special.Psi (psi)
00:08:18<A1kmm>digammas = [1..100000000]
00:08:19<A1kmm>result = sum digammas
00:08:21<A1kmm>main = putStrLn $ ((showString "Result = ") . (shows result)) ""
00:08:32<A1kmm>changed this to:
00:08:37<A1kmm>import Numeric.GSL.Special.Psi (psi)
00:08:39<A1kmm>import Control.Parallel.Strategies
00:08:40<A1kmm>digammas = map psi [1..100000000]
00:08:42<A1kmm>result = sum (parBuffer 10000 rnf digammas)
00:08:43<A1kmm>main = putStrLn $ ((showString "Result = ") . (shows result)) ""
00:08:54<Peaker>Cale: what example of a badly performing C program do you mean? In Haskell, there are tons of ways to make a program perform badly, in C, I think there are less so - and the ones that do - are explicit (explicitly copying stuff shows to the programmer that its expensive)
00:09:14<Peaker>Cale: C has far more transparent operational semantics on imperative computers, much easier to grok what's cheap and what's expensive
00:09:32<A1kmm>and timings are: first program: 30.202s
00:09:35<Cale>Peaker: There are a lot of ways to choose the wrong datastructure or the wrong algorithm.
00:09:37<newsham>peaker: you know people who know enough C to write correct code? :)
00:09:42<newsham>please have them send resume!
00:09:50<A1kmm>second program without -threaded: 56.136s
00:09:51<Twey>ACTION laughs.
00:09:54<Peaker>Cale: that's CS more than C, though
00:10:09<A1kmm>second program with -threaded and -N1: 6m24.522s
00:10:20<vininim>woah
00:10:23<Peaker>newsham: You don't need to know "enough" C, you need to limit yourself to a strict subset of C and rigourously enforce it by conventions
00:10:37<Cale>Peaker: The choices we make about datastructures and algorithms have to be different according to the evaluation model.
00:10:59<Peaker>newsham: I've worked in a C shop where non-trivial modules were bug-less to the best of our knowledge, and we had far far more extensive testing than any other place I know
00:11:17<Peaker>newsham: and by "bugless" I mean - the very extensive testing found almost nothing to begin with
00:11:22<Cale>Peaker: I'm not really contrasting C and Haskell, I'm contrasting strict/imperative or strict/functional programming with lazy/functional.
00:11:23<Peaker>newsham: (after the code reviews)
00:11:43<A1kmm>Cale: with -N10 -g10 on a 22 CPU shared memory system: 7m50s
00:11:47<newsham>[14:05] < Peaker> Cale: Knowing enough C to write correct programs and a bit of CS is enough to get fast-executing C.
00:12:16<Peaker>Cale: the thing is - the lazy/functional model maps less directly to our current hardware - its less transparent what the costs of operations are
00:12:24<Cale>A1kmm: Why are you using parBuffer?
00:12:51<Peaker>Cale: so given today's Von neumann imperative computers -- there's a bias for strict/imperative in terms of transparent operational semantics
00:13:01<newsham>"reasoning about time and space of lazy programs is not always easy."
00:13:03<A1kmm>So the map is evaluated ahead in parallel - is there a better approach?
00:13:04<Cale>A1kmm: How about something like parListChunk ?
00:13:26<newsham>anyway, I just wanted to bring that somewhat interesting blog to channel's attention
00:13:35<Peaker>newsham: if we used total languages -- it could mean we switch to strict evaluation - and maybe that would make things easier
00:13:49<Cale>Peaker: But it's still not hard to have a good model in your head which approximates the actual behaviour.
00:14:04<Cale>Peaker: Graph reduction is a reasonably good mental model, to start with.
00:14:53<A1kmm>Cale: I'm trying to sum over a big list... I think that would force the whole list to be kept in memory.
00:14:55<Peaker>Cale: I find it really difficult to reason in my head about how graph reduction is going to behave in a large program. I only have 1 year of Haskell-toying experience, barely any real work, though
00:16:03<Cale>Peaker: Yeah, it takes some time before it really gets ingrained into the way you picture things.
00:16:55<newsham>peaker: you're implying that the only reason to use lazy evaluation is because it increased convergence
00:17:01<newsham>but do you really believe that?
00:17:08<Cale>A1kmm: hmm, I suppose that's true, the contents of that list actually probably can't all fit in memory at once.
00:17:52<vininim>How does one make cabal install profiling versions of a library?
00:18:25<Peaker>newsham: I think it increases code-reuse in some (relatively rare, possibly) cases
00:18:43<Cale>A1kmm: I imagine that the problem is that the work necessary to compute one element of the list is dwarfed by the scheduling cost of a spark.
00:19:52<EvilTerran>ACTION 's main reason for liking lazy evaluation is that infinite or partial data structures allow some very snazzy idioms
00:20:08<newsham>*shrug* theres lots of reasons why lazy evaluation is attractive...
00:20:25<Peaker>newsham: what are they?
00:20:30<A1kmm>Cale: I guess there is a need for somehow combining chunking with only working to a certain distance ahead
00:20:45<EvilTerran>i guess my reason follows from the increased convergence
00:20:45<Peaker>EvilTerran: I like most the (take k . sort) example
00:20:47<newsham>it provides a clean way to separate out parts of the code that are usually intertwined.
00:21:12<newsham>in some cases it offers increased performance
00:21:38<EvilTerran>maximising convergence of your evaluation strategy maximises the choice of correct, terminating code within a given syntax
00:22:03<Peaker>newsham: yeah, though maybe lazy shouldn't be a default, I'm not sure
00:22:05<newsham>et: peaker's argument that is if your languae is total, the convergence is the same
00:22:09<EvilTerran>so allowing as many "snazzy idioms" as possible
00:22:16<newsham>peaker: perhaps not.. I'm not gonna argue that because I dont know
00:22:44<Cale>Peaker: If lazy isn't default, then you tend to get libraries with lots of strict functions which are less composable.
00:23:06<EvilTerran>newsham, well, yeah... if my language is total, though, surely evaluation order is irrelevant to semantics
00:23:06<Cale>(That is, strict, even though it would not hurt for them to be lazy)
00:24:18<newsham>excellent troll, btw. ;-)
00:24:24<Peaker>Cale: Yeah, I guess lazy is the better default. The trade-off between composability and transparent operational semantics is problematic here. Maybe a smart code editor could make some of these operational semantics more apparent
00:24:43<Peaker>EvilTerran: still affects operational semantics, though
00:25:14<Cale>Peaker: Imagining that things are as composable in a lazy language as they are in a strict one is also probably one of the big things that leads to inefficient beginner imperative code (I'm willing to bet)
00:25:19<EvilTerran>i mean, any expression would be arbitrarily strict (in every situation it's passed a _|_, ie never, it returns a _|_), *and* arbitrarily non-strict (it never returns a _|_)
00:25:19<Peaker>I guess totality is a little over-rated, because a program that finishes after the universe dies is not that great
00:25:22<Cale>er
00:25:32<Cale>Swap strict and lazy in that sentence :)
00:26:23<Peaker>Cale: Yeah, my first thoughts when introduced to laziness idioms in Haskell were: "I sometimes did that in imperative languages when I didn't care about performance, now it performs well too, cool!" :)
00:26:24<Cale>Quite often, to get good performance out of strict code, you more or less have to tear library functions open and write them by hand.
00:26:56<Cale>Imperative programmers do this so often that they don't even see it anymore.
00:27:17<shapr>Yup
00:27:44<Peaker>Cale: yeah, every piece of code could be said to be parameterized over a variety of things (functionality, programming language, strictness, ...) and thus we have a huge cartesian product body of code, when often there is a lot of code for the same functionality (due to various parameters being changed). laziness eliminates one parameter from the cartesian product
00:28:39<Peaker>I think having explicit file access in addition to a volatile memory store, rather than just one big persistent single-level store adds another parameter to this cartesian product (programs that work well over files, vs ones that are optimized to work "in memory")
00:29:08<shapr>Personally, I think your point is strongly in favor of open source.
00:29:16<shapr>And in favor of small simple naive functions that are easy to understand.
00:29:19<Peaker>shapr: I agree
00:29:40<shapr>Because I believe that source code should be tuned for ease of tearing apart.
00:29:57<shapr>Thus, tuned for ease of understanding.
00:30:06<Peaker>shapr: yeah, naive functions, sophisticated optimizers
00:30:12<shapr>Exactly
00:30:13<Cale>shapr: But it's also something that we should avoid the necessity of doing, as much as possible.
00:30:28<shapr>I'm not convinced of that.
00:30:40<Peaker>even better to be able to use rewrite rules to explain how the naive version becomes the sophisticated one, rather than just write the sophisticated one
00:31:14<Peaker>shapr: if we can compose naive functions together, rather than duplicate them a bit differently, of course we should do that?
00:31:15<Philippa>rewrite rules are far from the best possible way to do that
00:31:21<Philippa>but yeah, they beat no tools at all
00:31:23<shapr>I think that change will always be necessary, so it's best to make changes easy, as long as ability to understanding does not decrease.
00:31:30<Peaker>Philippa: what are better ways to do that?
00:31:44<Cale>Complicated programs are only made possible by abstractions that work. Abstractions are not doing their job if you have to get the source code and copy paste (or worse yet, write over again), then modify things a bit to get decent performance in your individual case.
00:32:03<Cale>Higher order functions are one way to save a lot of trouble here, laziness goes a bit further.
00:32:08<shapr>Yeah
00:32:08<Philippa>Peaker: well, a best possible way would allow me to specify to do certain things in a given position, where they can't just be applied generally
00:32:13<Peaker>shapr: I think the software world should mainly focus on eliminating parameters from this horrible cartesian product. We now have so many in there.
00:32:22<shapr>I can see the point of avoiding the necessity of tearing things apart.
00:32:36<Peaker>Philippa: location-specific rewrite rules?
00:32:43<shapr>But on the other hand, you can't future proof code except by making it easy to understand and modify for future needs.
00:33:01<Philippa>it's also likely to be more capable of introspection than rewrite rules are
00:33:09<shapr>What if memristors or quantum computing completely changes the face of computing?
00:33:26<Peaker>Philippa: Runtime-applied rewrite rules?
00:33:28<shapr>One reason UNIX beat VMS was that UNIX was easy to understand and port.
00:34:02<Cale>A1kmm: what happens if you turn that parameter to parBuffer way way down, like to, say, your number of processors
00:34:08<inimino>I think editor support for rewriting will help
00:34:18<A1kmm>Cale: let me try that.
00:34:41<Peaker>shapr: I don't see how the face of computing can be changed so badly that even extremely declarative programs (e.g FRP ones) would be affected.. they seem to me to be completely implementation-agnostic
00:34:47<Peaker>inimino: yes!
00:34:47<inimino>if you can see the naive code, the rules that optimize it, and the optimized code, along with assurances that they all give the same result, that would be worth a lot
00:35:01<shapr>The extreme case of my point is that a language should not require libraries, you should be able to just make what you need without much trouble.
00:35:02<Peaker>inimino: I think that's another strong point for a smart code editor
00:35:04<Cale>A1kmm: at least then not as many sparks will be created
00:35:15<Philippa>Peaker: no. Look, it's a damn huge research space, stop trying to get me to commit to an answer. Yours aren't the best possible either
00:35:15<shapr>Peaker: Er, tried to build GHC on ARM?
00:35:27<Cale>A1kmm: but the scheduling costs still might be too high, so you might really have to chunk things first.
00:35:47<Peaker>Philippa: I was trying to get you to clarify what you meant by "capable of introspection" -- doesn't it imply they're applied at runtime?
00:35:47<inimino>Peaker: yes, me too.
00:35:55<shapr>g'day Pseudonym
00:35:55<Philippa>Peaker: no, it doesn't
00:36:14<Philippa>it just means that they can examine what they're looking at /including semantic properties determinable at compile-time/
00:36:15<Peaker>Philippa: ah, so you mean the ability of the rewrite rule to dig deeper into the expressions?
00:36:22<shapr>Peaker: FRP programs may be implementation agnostic, but GHC is not.
00:36:28<Philippa>*argh*
00:37:29<Peaker>shapr: yeah, but if you eliminate all of the possible factors from the cartesian product, you may end up with a body of user-level software that should survive any computing implementation revolution -- the systems-software would have to change, of course
00:37:32<vininim>also, from the profiling info: not a good idea to use read inside a parser.
00:37:48<Philippa>Peaker: there is more to rewriting than syntax, FFS
00:38:09<Philippa>especially to rewriting /to achieve semantic aims/
00:38:48<Peaker>Philippa: maybe you can work on your anger problem? Note I did just ask questions, not state any fact
00:39:26<Cale>I wonder if it would be reasonable to introduce a standard system for expressing rewrite rules in Haskell programs, that is, one which could have a hope of being compiler-independent.
00:39:34<Philippa>Peaker: not an appropriate response
00:39:46<Cale>I suppose that if you want it to interact with things like inlining, the answer is no.
00:39:49<Peaker>Philippa: Ok
00:40:17<Peaker>shapr: I think if you eliminate the stuff from the product, you end up with a very small body of software that can do everything most desktops are used for.. (e.g: The STEPS project to write a desktop from ground up in 20KLOC)
00:40:52<shapr>Of course, if that were true, perhaps microkernels would rule the world.
00:41:07<Peaker>Philippa: what kind of semantic properties can you get at compile-time? Type information?
00:41:39<shapr>I take the dominance of monolitich kernels (Linux) over microkernels (HURD) as a point in favor of Cale's side of the discussion.
00:41:42<Philippa>Peaker: that's a starting point, yes
00:41:44<Peaker>shapr: kernels are another unnecessary parameter in the cartesian product, IMO :) Code inside kernel very different to user-code, but that isn't necessarily so, if you just use language-level protections instead
00:42:15<Philippa>Peaker: congratulations, you just made the RTS the new kernel
00:42:26<Peaker>Philippa: indeed, and its a much smaller one. Drivers are just libraries
00:42:31<Cale>Yeah, I wonder why microkernels have failed. Has there ever been a microkernel which offered higher-order primitives?
00:42:52<Peaker>Philippa: lack of memory separation may have very desirable properties, decreasing unnecessary copying and cache flushes
00:43:07<p_l>Cale: Microkernels probably failed due to Mach :>
00:43:07<shapr>Peaker: I'd want to see a running example before I'd believe that.
00:43:10<Philippa>Peaker: you still need to write the RTS in something
00:43:32<p_l>Peaker: Bell Labs' Inferno, Microsoft's Singularity
00:43:42<p_l>damn, that was for shapr
00:44:11<inimino>microkernels probably failed because of Linux
00:44:13<p_l>shapr: those two use managed VM in place of normal memory separation
00:44:17<Peaker>Philippa: Some of the RTS may need to use a lower-level language, and some of the libraries that it uses would have to be duplicated for it - so I still have a parameter in the cartesian product, but hopefully it applies to much less code (only the generic libraries the RTS code uses have to be duplicated differently)
00:45:00<p_l>inimino: not really - there exist few successful micro/nanokernel systems, two of them having connection with Mach. Original Mach gave a very bad name to microkernels
00:45:21<p_l>and L4/Linux actually managed to beat linux in terms of performance on Arm
00:45:43<inimino>p_l: partly tongue-in-cheek
00:46:00<inimino>p_l: I think they failed by a historical accident, of which Linux is certainly a part... it's just too hard to turn everything on its head at this point
00:46:09<p_l>inimino: Mach truly sucked :P
00:46:10<Peaker>I think the correct transition to language-level protections, though, may be after we have dependent types
00:46:43<inimino>Peaker: so you're a fan of Oberon?
00:46:50<Peaker>inimino: what's that?
00:46:58<p_l>inimino: there are two (known to me), Mach-based systems that managed to get far enough. Both had decided to run their servers inside kernel mode, afaik
00:47:43<inimino>it's an OS written in Modula-3 IIRC
00:47:51<p_l>one was OSF/1, at least DEC's version. The other one is OS X
00:47:56<p_l>inimino: it's written in Oberon :)
00:48:06<inimino>oh, ok
00:48:08<A1kmm>cale: 7m34.100s with 10 processors, and a look-ahead of 10.
00:48:10<sclv_>I was about to say...
00:48:15<Peaker>inimino: sounds like it could be nice, but there are tons of things that need to be right as well
00:48:15<inimino>it's been a while since I read those papers, sorry ;-)
00:48:24<p_l>inimino: and for some reason doesn't have preemptive scheduler
00:49:12<inimino>well it was written in some ridiculously small number of lines of code
00:50:33<sw17ch>can some one tell me why these view patterns overlap?
00:50:33<lambdabot>sw17ch: You have 1 new message. '/msg lambdabot @messages' to read it.
00:50:34<sw17ch>http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5478#a5478
00:52:00<sw17ch>it's my first foray into view patterns and i don't see why they overlap
00:55:29<sw17ch>ah: http://hackage.haskell.org/trac/ghc/ticket/2395
00:57:19<vininim>um, (atto)parsec might not be the best choice for parsing
00:57:42<vininim>also, nifty parsecing:
00:58:34<vininim>http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5479#a5479
00:59:24<shapr>Oberon is really nifty.
01:01:28<mmorrow>sw17ch!
01:01:28<lambdabot>mmorrow: You have 1 new message. '/msg lambdabot @messages' to read it.
01:01:35<sw17ch>mmorrow!
01:01:43<mmorrow>sw17ch: :)
01:33:46<keseldude>> let (+) x y = succ . sum $ [x,y] in 2 + 2
01:33:51<lambdabot> mueval-core: Prelude.read: no parse
01:33:51<lambdabot> mueval: ExitFailure 1
01:35:11<mmorrow>> let (+) x y = succ . sum $ [x,y] in 2 + 2
01:35:14<lambdabot> 5
01:35:19<mmorrow>weird
01:37:36<psygnisfive>why weird?
01:38:25<sm>evening all
01:38:43<mmorrow>it failed for unknown reasons when keseldude tried
01:38:50<mmorrow>evening
01:39:42<psygnisfive>oh, so it did
01:40:00<psygnisfive>magic!
01:40:54<aavogt>quite the referentially transparent lambdabot
01:43:20<jbauman>> let (+) x y = succ . sum $ [x,y] in 2 + 2
01:43:23<lambdabot> 5
01:43:41<vininim>> let (+) x y = succ . sum $ [x,y] in 2 + 2
01:43:43<lambdabot> 5
02:03:31<gwern>aavogt: every evaluated expression in lambdabot is in a race condition
02:03:47<gwern>so it's not surprising that the same eval can have different results at different times
02:05:12<Twey>gwern: *wince*
02:05:46<gwern>in an irc channel of infallible angels, that needn't be the case. but alas, we are only men and mortals
02:06:27<gwern>(specifcally, the expressions are racing to be evaluated before either the watchdog thread or process kill mueval)
02:06:56<kpreid>and the watchdog says "no parse"?
02:07:21<gwern>the internals are a bit odd. I could see that being an error message
02:17:15<aconbere>anyone know anything about using edgeflags in hopengl?
02:17:32<sclv_>gwern: or before a netsplit hoses the reply :-)
02:20:54<joaopizani>Good evening everyone. I'd llike some advice on using the Data.Graph module
02:21:23<joaopizani>I've read the official haddock for the module, and haven't found a way to have a label on the graph's edges
02:21:43<joaopizani>Do you know of some way to label the edges of a Data.Graph?
02:24:17<joaopizani>I'm working on a project that involves the manipulation and visualization of finite automata, regular expressions and context-free grammars
02:25:01<joaopizani>My plan is to use the Haskell GraphViz binding for the visualization part, but the toGraphviz function requires a Data.Graph as input
02:25:31<joaopizani>and I want to have the input symbols displayed above the arrows
02:33:02<aavogt>> fix (+1)
02:33:07<lambdabot> mueval-core: Prelude.read: no parse
02:33:07<lambdabot> mueval: ExitFailure 1
02:33:46<aavogt>gwern: so it seems. I consider that a terrible error message
02:34:06<gwern>ACTION shrugs
02:34:17<Gracenotes>that usually means a stack overflow
02:34:23<gwern>mueval has bigger fish to fry; I'd like to run on windows, for example
02:34:29<Gracenotes>could also be an overflow issue
02:34:40<Gracenotes>like, as in heap
02:35:07<gwern>Gracenotes: as in, the expression has heap big problem?
02:41:29<ctran>how close can haskell get to C for this problem? http://www.codechef.com/problems/FCTRL/
02:43:29<ctran>any help?
02:43:33<dmwit>?tell joaopizani I don't know of a way to use Data.Graph for edge-labelled graphs, unfortunately. However, with the GraphViz module you can build the graph description yourself, in which case edge-labellings are Totally Plausible.
02:43:33<lambdabot>Consider it noted.
02:43:48<dmwit>Why would you want to be close to C?
02:44:02<ctran>just learning to write better haskell
02:44:18<dmwit>Good Haskell is not close to C; it's not even close to good C.
02:44:44<monochrom>What is "close"?
02:44:49<ctran>anything I can do to improve http://gist.github.com/121948
02:45:45<inimino>why wouldn't you want to be close to C?
02:45:48<ctran>close in term of speed/efficiency
02:45:52<inimino>assuming he meant performance
02:46:02<dmwit>Oh, for performance.
02:46:12<dmwit>I thought he meant code that looked like C.
02:46:17<ctran>sorry i should have been more clearer
02:46:58<MyCatVerbs>You can write code that looks roughly like Pascal, without excessive difficulty.
02:47:35<MyCatVerbs>C is harder, because writing a DSL that gives you lvalues is awkward, but I think it's been done. Can't remember who did it, though.
02:48:31<dmwit>> iterate (`div` 5) 625
02:48:31<dibblego>are ap and (<*>) for ((->) t) the same function with arguments flipped about?
02:48:36<lambdabot> mueval-core: Prelude.read: no parse
02:48:37<lambdabot> mueval: ExitFailure 1
02:48:38<dibblego>er, ep and (>>=)
02:48:43<dibblego>er, ap and (>>=)
02:48:49<dmwit>no parse?
02:48:57<dmwit>dibblego: ap and (>>=) are not the same
02:48:58<Gracenotes>ap is (=<<) . flip
02:49:08<Gracenotes>(=<<) is ap . flip
02:49:09<dibblego>not the same for the general case
02:49:13<Gracenotes>for (->)
02:49:14<dmwit>:t ap
02:49:20<dibblego>Gracenotes, just checking, thanks
02:49:26<lambdabot>forall (m :: * -> *) a b. (Monad m) => m (a -> b) -> m a -> m b
02:50:10<dmwit>ctran: You might like "iterate (`div` 5)".
02:50:27<Gracenotes>> ((,) =<< length) "hello"
02:50:32<Gracenotes>> ((,) <*> length) "hello"
02:50:33<lambdabot> mueval-core: Prelude.read: no parse
02:50:33<lambdabot> mueval: ExitFailure 1
02:50:37<Gracenotes>lols.
02:50:38<lambdabot> mueval-core: Prelude.read: no parse
02:50:38<lambdabot> mueval: ExitFailure 1
02:50:59<Gracenotes>(5,")
02:51:06<dmwit>ctran: print = putStrLn . show
02:51:09<BMeph>MyCatVerbs: Our resident maker-of-interpreters-of-other-lamguages, of course - augustss. :)
02:51:12<Gracenotes>ahem. (5, "hello") and ("hello", 5)
02:51:30<MyCatVerbs>BMeph: ah! I knew it was somebody who frequents here, but couldn't quite remember. Thank you.
02:51:31<dmwit>:t maybe (putStrLn "error") (print . fst)
02:51:40<Gracenotes>>:[
02:51:43<lambdabot>forall a b. (Show a) => Maybe (a, b) -> IO ()
02:52:10<dmwit>:t \fcntrl -> maybe (putStrLn "error") (print . fcntrl . fst)
02:52:17<lambdabot>forall c a b. (Show c) => (a -> c) -> Maybe (a, b) -> IO ()
02:52:41<dmwit>ctran: You have way too much code. ;-)
02:53:18<dmwit>:t \f -> interact (unlines . f . lines)
02:53:19<ctran>dmwit: sorry :-)
02:53:25<lambdabot>([String] -> [String]) -> IO ()
02:53:57<ctran>dmwit: it will get shorter in a year, I hope
02:54:02<dmwit>:t \fcntrl -> interact (unlines . map (show . fcntrl . read) . lines)
02:54:03<BMeph>showIntAtBase 5, maybe? :)
02:54:11<lambdabot>forall b c. (Show c, Read b) => (b -> c) -> IO ()
02:56:52<dmwit>ctran: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5480#a5480
02:57:13<dmwit>Oops, didn't notice the "tail" right before C.lines in your paste.
02:57:19<dmwit>whatever
02:57:35<ctran>no problem
02:57:56<dmwit>It shouldn't be hard to adapt to ByteString if you actually find out that the IO is a performance bottleneck.
02:58:23<ctran>wow, your version is the exact reason I want to learn haskell
02:58:57<centrinia>> (\b x -> snd $ until ((==0) . fst) (\(a,b) -> id *** (:b) $ (a `divMod` b)) (x,[])) 10 12341
02:59:02<lambdabot> mueval-core: Prelude.read: no parse
02:59:02<lambdabot> mueval: ExitFailure 1
02:59:10<gwern>hm, takeWhile >0 . drop 1 looks suspicious to me
02:59:23<dmwit>centrinia: \bot seems to have acid reflux for now
02:59:32<dmwit>gwern: Nonsense, they operate on two different ends of the list.
02:59:58<dmwit>gwern: The alternative is
03:00:09<dmwit>sum . takeWhile (>0) . iterate (`div` 5) . (`div` 5)
03:00:13<dmwit>which is even more suspicious.
03:03:20<ctran>dmwit: is there a function to turn Int -> ByteString ?
03:03:36<dmwit>oh, uh... dunno
03:03:45<dmwit>I'd be awful surprised if the answer was no.
03:03:50<dmwit>?hoogle Int -> ByteString
03:03:50<lambdabot>Data.ByteString.Internal unsafeCreate :: Int -> (Ptr Word8 -> IO ()) -> ByteString
03:03:50<lambdabot>Data.ByteString replicate :: Int -> Word8 -> ByteString
03:03:50<lambdabot>Data.ByteString.Char8 replicate :: Int -> Char -> ByteString
03:03:57<dmwit>?hoogle+
03:03:58<lambdabot>Data.ByteString drop :: Int -> ByteString -> ByteString
03:03:58<lambdabot>Data.ByteString take :: Int -> ByteString -> ByteString
03:03:58<lambdabot>Data.ByteString.Char8 drop :: Int -> ByteString -> ByteString
03:04:01<dmwit>bleh
03:04:45<dmwit>I sure don't see one.
03:05:07<dmwit>pack . show ;-)
03:07:57<mgsloan>?hoogle Integer -> ByteString
03:07:58<lambdabot>Data.ByteString unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString
03:07:58<lambdabot>Data.ByteString.Lazy unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString
03:07:58<lambdabot>Data.ByteString.Char8 unfoldr :: (a -> Maybe (Char, a)) -> a -> ByteString
03:08:10<mgsloan>hrmm
03:08:57<ctran>thanks everyone, i have enough ideas to play with for now
03:51:01<Reiv>Hrm
03:51:19<Reiv>http://pastebin.com/dfd19651 - I've got brackets working. Now I need to get identifiers (variables) readable.
03:51:27<Reiv>My problem here is that they're fairly arbitary. :/
03:59:20<Reiv>So I'm just a little unsure how to implement it...
04:01:20<jaredj>do { openTag "CHECKNUM"; TagText checkNumber <- anyToken; return checkNumber }
04:01:27<jaredj>is there a way to do that with >>=?
04:01:39<jaredj>(particularly: the pattern match)
04:02:06<jaredj>without a lambda?
04:02:09<BMeph>jaredj: "You're soaking in it." ;p
04:03:27<Twey>jaredj: If you create a deconstructing function, sure
04:03:52<jaredj>like \TagText x -> x
04:04:03<Twey>That's a lambda
04:04:10<jaredj>yes
04:04:20<Twey>openTag "CHECKNUM" >> anyToken >>= return . deTagText
04:04:30<Twey>where deTagText (TagText x) = x
04:06:36<jaredj>yes - i wasn't sure if you could get around making one of those
04:06:57<jaredj>i should have asked if there was a simpler way to do that do-construct
04:07:25<jaredj>BMeph: i had to everything2 your quote ;P
04:15:37<MyCatVerbs>comonad.com is edwardk, right?
04:16:17<MyCatVerbs>Oh right yes, he prints his name on the blog posts. Hah, I probably should not have missed that. :)
04:17:31<Reiv>Huh.
04:17:41<Reiv>Hi, MCV!
04:18:07<MyCatVerbs>Greetings, Reiver. Nice to see a few nightstar denizens around.
04:18:20<Reiv>Oh, aye.
04:18:33<Reiv>#Code is a wonderful resource, but sometimes you just can't beat the source. ;)
04:18:51<MyCatVerbs>I'm vaguely surprised that McMartin doesn't idle in here too.
04:18:55<p_l>ACTION looks outside, sees light
04:19:18<copumpkin>ACTION looks outside, sees darkness
04:19:26<copumpkin>can darkness be seen?
04:19:35<p_l>nope
04:19:52<p_l>well, not physically, I guess. Languages don't care
04:20:41<monochrom>can non-termination be observed? :)
04:21:35<MyCatVerbs>Reiv: I guess not. On the flip side, you get a lot more newbie questions in here, and answering those is pretty decent karma. :)
04:21:37<psygnisfive>monochrom: by a hyperturing machine, sure!
04:21:50<monochrom>hehe
04:21:58<MyCatVerbs>Can that machine's failure to terminate be observed?
04:22:16<monochrom>I wonder if darkness is analogous to non-termination.
04:22:19<psygnisfive>i dont know if hyperturing machines have those same constraints
04:22:21<mmorrow_>what's the definition of "observe" (in the CS sense)?
04:22:27<psygnisfive>monochrom: what? no. what?
04:22:33<MyCatVerbs>Actually, non-termination is easy. You know that scene with Arnold and the minigun, where he shoots up an entire parking lot and deliberately kills no-one? Yeah, that.
04:22:46<monochrom>hahahahaha
04:22:57<psygnisfive>how would darkness be analogous to non-termination?
04:22:58<mmorrow_>MyCatVerbs: but only TERMINATors can do that
04:23:21<monochrom>That's what "I wonder if" means. I don't know.
04:23:30<MyCatVerbs>mmorrow_: Oh, it's a bugger to pull off, sure. But watching it isn't challenging.
04:23:36<psygnisfive>.. no. its not analogous at all.
04:23:40<hackagebot>urlencoded 0.2.0.0
04:23:40<psygnisfive>darkness is analogous to an empty list.
04:23:47<mmorrow_>ACTION googles the CS definition of "observe"
04:23:48<psygnisfive>or the emptiness of the list.
04:23:55<monochrom>Hey I can take advantage of people failing to read and succeeding in getting fully surprised!
04:24:02<monochrom>I wonder if P=NP.
04:24:08<monochrom>I wonder if P/=NP
04:24:26<MyCatVerbs>monochrom: I hope not, and I hope not, respectively.
04:24:27<psygnisfive>i suspect P=NP.
04:24:43<monochrom>I wonder if Haskell is untyped.
04:24:52<psygnisfive>well, actually, maybe not
04:24:57<psygnisfive>travelling salesman is i think NP
04:25:11<psygnisfive>and i dont think theres any conceivable deterministic way to computer travelling salesman
04:25:12<MyCatVerbs>On the one hand, P=NP breaks pretty much all reasonable crypto you could come up with. On the other hand, P/=NP means that lots of useful problems can't be completely solved. :/
04:25:15<psygnisfive>but i could be wrong!
04:25:18<mmorrow_>so is (the general case of) graph coloring
04:25:33<psygnisfive>can someone explain the state monad to be?
04:25:45<mmorrow_>traveling salesman is one of the NP poster-boys
04:25:47<dmwit>Yes!
04:25:48<psygnisfive>i mean, i dont understand monads in general but thats ok
04:25:54<dmwit>?go you could have invented monads
04:25:56<lambdabot>http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html
04:25:56<lambdabot>Title: A Neighborhood of Infinity: You Could Have Invented Monads! (And Maybe You Alrea ...
04:26:03<dmwit>also
04:26:25<dmwit>?where all about monads
04:26:26<lambdabot>I know nothing about all.
04:26:28<psygnisfive>see, i figure that like
04:26:30<dmwit>http://www.haskell.org/all_about_monads/html/index.html
04:26:41<psygnisfive>you can sythesize state
04:26:53<MyCatVerbs>Isn't even 3-colouring NP-complete?
04:27:00<monochrom>Anyway, I use "observe" in the physics sense. I don't think there is a widely adopted CS sense.
04:27:09<psygnisfive>by passing around a hash of varname-varvalue pairs that gets mapped in each iteration
04:27:12<psygnisfive>you know what i mean?
04:27:39<dmwit>psygnisfive: Yep. The idea of the State monad is to pass those things for you.
04:27:47<dmwit>psygnisfive: Also, typically, instead of a hash, we use a record.
04:27:52<mmorrow_>hmm, it look like "observe" isn't formally defined (wrt CS), it's just in various "you know, like looking" ways (?)
04:27:53<dmwit>So no hashing, just access the data you want.
04:27:55<psygnisfive>well see dmwit, problem i see with that is that
04:28:04<mmorrow_>*it's just used in ...
04:28:06<psygnisfive>thats effectively precisely what reassignable variables are.
04:28:14<dmwit>mmorrow_: Well, there's barbs as in the pi-calculus.
04:28:23<dmwit>mmorrow_: And there's contextual equivalence for functional calculi.
04:28:25<mmorrow_>dmwit: what is that?
04:28:35<psygnisfive>actually, reassignable variables are also i guess like nested lets
04:28:40<mmorrow_>i'm looking for the definition of "observe"
04:28:43<dmwit>mmorrow_: A barb is a process offering to send on a named channel, where the name is free.
04:28:46<psygnisfive>or lambdas
04:29:03<dmwit>mmorrow_: So "observation" involves what channels with free names are offering to send.
04:29:04<psygnisfive>let x = 5 in (let x = x*x in x)
04:29:13<mmorrow_>i don't see how terms can be used without definitions, so i feel like it has to be defined somewhere
04:29:16<psygnisfive>i dont know if that precisely will work in haskell, but you can convert it down to lambdas and get the same
04:29:32<dmwit>mmorrow_: Similarly, for typed calculi, observation involves putting the thing you're observing into arbitrary contexts.
04:29:44<dmwit>mmorrow: Terms that converge or diverge together in all contexts are observationally equivalent.
04:29:55<copumpkin>psygnisfive: that's how people often implement tight loops
04:30:01<psygnisfive>tight loops?
04:38:24<mmorrow>dmwit: hmm
04:38:24<mmorrow>dmwit: so "observe" := ?
04:38:24<mmorrow>@wn observe
04:38:24<mmorrow>@wd observe
04:38:24<mmorrow>@w observe
04:38:37<MyCatVerbs>ray: n+k patterns are evil. :)
04:38:37<timmaxw>Why did "let 2+2=5" work?
04:38:37<MyCatVerbs>ray: and/or unclean.
04:38:37<ray>where's the n+k pattern
04:38:37<copumpkin>it redefined (+)
04:38:37<ray>STOP SPLITTING FREENODE
04:38:38<copumpkin>ugh
04:38:38<monochrom>It is non-exhaustive pattern, not n+k pattern.
04:38:38<MyCatVerbs>> do { a <- "aaa"; a <- ord a : []; return (a+1); }
04:38:38<dmwit>timmaxw: let (+) = \a b -> case (a, b) of (2, 2) -> 5 in 3 + 3
04:38:38<lambdabot> [98,98,98]
04:38:38<timmaxw>yes, clever
04:38:38<ray>non-exhaustive doesn't seem like quite the right way to put it since it's in a let
04:38:38<MyCatVerbs>Hee. The old and new bindings don't even have to have the same type.
04:38:38<psygnisfive>ray: its not just freenode splitting, interestingly
04:38:38<psygnisfive>my chat clients are dying too
04:38:40<dmwit>ray: What does let have to do with it?
04:38:49<dmwit>> let 2+2 = 5; 3+3 = 7 in 3+3
04:38:53<timmaxw>why are functional dependencies necessary in multiparameter type classes?
04:38:55<lambdabot> 7
04:39:01<ray>that's what
04:39:05<monochrom>"let" doesn't change anything.
04:39:07<dmwit>timmaxw: They're not.
04:39:27<dmwit>timmaxw: They're useful because they help pin down instances for inference, but they're definitely not necessary.
04:39:34<timmaxw>so the "Mult" example with matrices and vectors that I see in every tutorial on them, doesn't actually need them?
04:39:57<monochrom>I mean, it's "let" and it's still non-exhaustive pattern. You could have defined your + with exhaustive patterns, under "let".
04:40:00<dmwit>No; with type-annotations sprinkled around, those same examples would work without the functional dependencies.
04:40:01<mmorrow>whoa, everyone just split, returned, and then 20 lines of conversation all appeared in one big scroll
04:40:07<ray>> let (+) = const in 2+2
04:40:10<psygnisfive>ok i need to be off to do some coding. :P
04:40:12<MyCatVerbs>timmaxw: All that happens if you don't have them is that you wind up needing more type declarations in funny places.
04:40:13<lambdabot> mueval-core: Prelude.read: no parse
04:40:13<lambdabot> mueval: ExitFailure 1
04:40:16<psygnisfive>afk.
04:40:17<mmorrow>ACTION was starting to think he was disconnected
04:40:47<timmaxw>suppose that we define class Mult a b c where (*) :: a -> b -> c
04:41:03<timmaxw>and define an instance where (*) :: Matrix -> Matrix -> Matrix
04:41:09<lament>mmorrow: it's not you, it's the rest of the universe.
04:41:17<mmorrow>lament: i knew it!
04:41:22<timmaxw>shouldn't the compiler be able to tell that if m1,m2::Matrix, then (m1*m2)::Matrix?
04:41:29<dmwit>timmaxw: nope
04:41:33<timmaxw>why not?
04:41:41<dmwit>timmaxw: Nothing is stopping you from declaring an instance later for Mult Matrix Matrix Vector.
04:41:53<timmaxw>why can't the compiler look for that?
04:41:56<dmwit>timmaxw: Nothing, that is, except functional dependencies. =)
04:42:04<dmwit>timmaxw: separate compilation
04:42:11<dmwit>timmaxw: The instance might be in another file.
04:42:51<timmaxw>doesn't the compiler detect duplicate instances even if they are in separate files? or no?
04:43:09<monochrom>> let { 0+n=n; (m+1)+n = succ(m+n) } in 2+2 {- this one will cause a flame war -}
04:43:15<lambdabot> mueval-core: Prelude.read: no parse
04:43:15<lambdabot> mueval: ExitFailure 1
04:43:21<ray>what if it's linked in at runtime
04:43:22<monochrom>Hrm!
04:44:27<dmwit>timmaxw: It does detect multiple instances, yes.
04:44:46<timmaxw>dmwit: but the instance might be in another file...
04:44:52<dmwit>Yes, I know.
04:44:59<dmwit>I'm not totally sure what's going on here.
04:45:04<monochrom>It works in GHC.
04:45:06<dmwit>(I knew at one point...)
04:45:06<ray>your head a splode
04:46:32<mmorrow>squirting brain goo all over the room like a loose fire hose
04:48:08<dmwit>timmaxw: Aha, I got it.
04:48:16<dmwit>...I lied.
04:48:54<dmwit>No, I do have it.
04:49:02<dmwit>timmaxw: Constraints can only mention type variables.
04:49:13<dmwit>timmaxw: So (Mult Matrix Matrix c) is not a valid constraint.
04:49:56<timmaxw>dmwit: ah... but i'm not sure how functional dependencies solves that... let me think on it a bit
04:49:56<dmwit>bah, FlexibleContexts is for exactly that
04:50:31<dmwit>Well, functional dependencies let us say, "when we know a and b, then we know c", so we don't need a constraint that looks like that.
04:50:44<dmwit>We know a and b, so conceptually we should know c.
04:50:49<timmaxw>dmwit: suppose we define Mult with a functional dependency
04:51:01<timmaxw>dmwit: then what would the constraint look like on (m1*m2) where m1,m2::Matrix?
04:51:50<dmwit>It would likely either complain (if there were no instance for Matrix Matrix c), or simply choose the type c (if there is an instance Matrix Matrix c).
04:52:12<dmwit>But I am so unsure of this.
04:52:28<dmwit>I am a type-system newbie myself. =P
04:52:35<timmaxw>dmwit: But if there's an instance (Mult Matrix Matrix Matrix) and Mult is defined with a functional dependency, then it chooses the type Matrix. I think.
04:52:45<dmwit>right
04:53:01<dmwit>If you substitute "Matrix" for "c" in the sentence above, that's exactly what I predict.
04:53:29<dmwit>But more importantly, if you then try to add an instance Matrix Matrix Int, it will complain loudly.
04:53:33<timmaxw>dmwit: It chooses Matrix by searching through the known instances of Mult and looking for one of the form (Mult Matrix Matrix <something>)
04:53:41<dmwit>I... think so.
04:53:52<timmaxw>dmwit: why does it need the functional dependency to make that decision?
04:54:02<bogner>is there magic involved in turning [a] into tring, when inferring types?
04:54:14<bogner>s/tring/String/
04:54:14<dmwit>timmaxw: That is the bit I don't know.
04:54:26<dmwit>bogner: type String = [Char]
04:54:30<rick_2047>ls
04:55:20<dmwit>bogner: Other than the usual unification, no magic, I think.
04:55:30<bogner>dmwit: I realize that, but if I create data Foo = Foo String, I end up getting issues with couldn't match expected type [b] against inferred type Foo
04:55:39<bogner>when trying to use concatMap
04:55:52<dibblego>bogner, data and type do different things
04:55:53<dmwit>bogner: But Foo doesn't unify with [b].
04:56:11<bogner>how can I make it unify with [b]?
04:56:18<timmaxw>bogner: if you want Foo and String to be the same thing, you need "type Foo = String"
04:56:31<dibblego>data Foo = Foo { foo :: String } -- the use Foo and foo to wrap/unwrap
04:56:55<bogner>timmaxw, dibblego: then it doesn't have a distinct identity, so I can't make useful instances of classes
04:57:00<monochrom>(There is no Matrix.)
04:57:10<bogner>dibblego: that might do it
04:57:14<dibblego>bogner, sure you can, instance Monoid Foo where ...
04:57:31<bogner>dibblego: I meant in the type Foo = String case
04:57:36<dmwit>dibblego: I think he was complaining about your earlier "type" suggestion, not your later "data" suggestion. =)
04:57:47<bogner>dmwit: thanks for clearing that up
04:57:52<dibblego>I didn't suggest type
04:57:59<dmwit>bogner: Also, if you're using this *only* to trick the type-system into thinking there's two types when really there's only String, then may I suggest newtype?
04:58:33<bogner>dmwit: using newtype didn't seem to fix the unifying thing, perhaps I'm misunderstanding how to use it?
04:58:34<dmwit>bogner: You use it exactly the same way, but save one indirection on each use.
04:58:43<dmwit>bogner: (i.e. exactly the same way as data)
04:58:44<dibblego>bogner, replace data with newtype
04:59:12<monochrom>newtype Foo = FooConstructor String
04:59:20<dmwit>bogner: Yes, you still have to manually wrap and unwrap it.
04:59:41<dmwit>bogner: The only difference is that wrapping and unwrapping get optimized away for newtypes, but not for data types.
04:59:42<bogner>dmwit: how do I unwrap it, then?
04:59:49<bogner>for a newtype
04:59:57<monochrom>pattern-matching
05:00:00<dmwit>newtype Foo = Foo { unFoo :: String } -- exact same way
05:00:01<dibblego>newtype Foo = Fo o { foo :: String }
05:00:04<dmwit>Pattern-matching works, too.
05:00:07<monochrom>f (FooConstructor s) = s
05:00:25<bogner>oh, cool, I didn't realize that record syntax would work there
05:00:28<bogner>awesome
05:00:33<bogner>thanks guys
05:00:34<dibblego>foo :: Foo -> String
05:00:41<dibblego>Foo :: String -> Foo
05:01:10<timmaxw>regarding the difference between newtype and data: it looks to me like the only difference between newtype and data-with-one-constructor is in the way they are implemented at runtime
05:01:13<timmaxw>right?
05:01:17<dmwit>newtype X = X X -- try it at home, kids!
05:01:30<dibblego>timmaxw, bottoms matter
05:02:08<timmaxw>dibblego: good point.
05:02:40<dmwit>(Constructor undefined) -- actually undefined for newtype, a wrapped-up undefined for data
05:03:09<leimy_>I need to convert Word16 to Int or Int64
05:03:10<cads>eexcellent, I can (defmacro λ ....)
05:03:18<leimy_>what's the easy way to do that?
05:03:18<dmwit>:t fromIntegral
05:03:27<lambdabot>forall a b. (Integral a, Num b) => a -> b
05:03:39<leimy_>clever
05:03:42<leimy_>:-)
05:03:44<dmwit>=)
05:03:50<leimy_>I don't know why I always forget that :-)
05:03:54<cads>,(λ [x] (* x x))
05:03:58<lunabot> luna: Not in scope: `Û§
05:04:19<timmaxw>dibblego, dmwit: is that behavior particularly useful?
05:04:27<dmwit>timmaxw: Nope, just something to watch out for.
05:05:09<timmaxw>dmwit: then why does newtype exist at all? why not just say that the compiler "should" optimize instances of data with a single declaration?
05:05:31<dmwit>Because they behave differently.
05:05:37<leimy_>Data.Binary is telling me: too few bytes. Failed reading at byte position 20
05:05:46<leimy_>but I'm telling it to read 19 bytes :-)
05:05:47<dmwit>You can't optimize them just because you *think* people are going to use them in a way that doesn't break the optimization.
05:05:48<leimy_>so I'm confused :-)
05:06:07<timmaxw>dmwit: are there any differences other than the behavior around _/_ and the runtime implementation?
05:06:19<dmwit>Nope.
05:06:24<dmwit>But _ is a useful value at runtime.
05:06:26<dmwit>We use it all the time.
05:06:41<timmaxw>and the behavior around _/_ is "something to watch out for"?
05:06:49<dmwit>You bet!
05:06:58<dmwit>It won't be a problem until you forget to watch for it. ;-)
05:07:42<dmwit>Try "newtype X = X X deriving Show" and then type "undefined :: X" in a ghci terminal.
05:07:51<dmwit>Predict what it will do and see if you're right. =)
05:08:24<timmaxw>why was newtype originally put into the Haskell 98 report then? why not just include a suggestion that compilers optimize data? i don't see how adding a new behavior that acts a tiny bit differently is worth the added language complexity (and confusion to newbies)
05:08:57<MyCatVerbs>@where lyah
05:08:58<lambdabot>www.learnyouahaskell.com
05:09:25<dmwit>timmaxw: ...
05:09:30<timmaxw>dmwit: i wouldn't expect it to accept "newtype X = X X" at all
05:09:35<timmaxw>dmwit: that's what i would *predict*
05:09:38<dmwit>timmaxw: You *can't* optimize data in general.
05:10:04<thoughtpolice>timmaxw: because then you have to treat that optimization as a standard
05:10:28<thoughtpolice>because then code may depend on such functionality as specified by the report
05:10:46<thoughtpolice>it's the same reason they didn't totally kill the monomorphism restriction
05:10:55<dmwit>Detecting when somebody is using data as newtype (i.e. finding "undefined"s in the code) is undecidable.
05:10:57<thoughtpolice>they didn't want the potential performance problems to be held at the mercy of every implementation
05:11:05<timmaxw>dmwit: oh, i think i see it. if "newtype X = X Foo", then there's one possible variation at runtime: "X". If "data X = X Foo", then there are two possible variations: "X" and "_/_". This means that more space has to be used for the "data" declaration. Am I right?
05:11:22<dmwit>timmaxw: Exactly.
05:11:29<timmaxw>also, ghci won't let me run "newtype X = X X"
05:11:40<dmwit>timmaxw: Yeah, you've got to put newtype declarations in a file.
05:11:42<timmaxw>or any "newtype" declarations at the interactive prompt
05:11:59<dmwit>That's why I said to try newtype X = X X deriving Show, *then* go to ghci. ;-)
05:12:44<timmaxw>thoughtpolice: why? it's trivial to implement and it doesn't make a huge performance impact either way. compilers can easily include it or not include it. isn't that like saying that common subexpression elimination has to either be part of the standard or not available at all?
05:13:01<timmaxw>thoughtpolice: (that is, if it weren't for the _/_ thing)
05:13:28<dmwit>It's not trivial to implement, it can make a huge performance difference, and it's not at all like saying something must be available or not available.
05:14:21<dmwit>Strictness analysis is a field with lots of papers and a load of very difficult work.
05:14:27<timmaxw>dmwit: i see.
05:14:30<dmwit>So that's the trivial to implement thing.
05:14:46<dmwit>Wrapping and unwrapping a single constructor can really matter, especially for arithmetic or so.
05:14:49<dmwit>So that's the performance thing.
05:15:14<dmwit>(Imagine following a pointer, doing arithmetic, and then allocating a new pointer every time you wanted to add. yuck)
05:15:31<dmwit>As for the standard, it doesn't come out either way.
05:15:35<amckinley>hey, i need some help writing a line-oriented parsec parser. im trying to parse dns zone files (see http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5483)
05:15:54<dmwit>That lowers the bar for standards-compliant compilers (a good thing), and lets serious compilers do the optimization if it can (also a good thing).
05:16:20<amckinley>i dont want to use lexeme parsers because whitespace is meaningful in a couple complicated ways, and im having trouble doing things without them
05:16:55<timmaxw>dmwit: it adds a little complexity to the language and makes it easier for non-optimizing compilers not to have horrible performance
05:17:15<dmwit>Right.
05:17:24<dmwit>A relatively benign trade-off, really.
05:18:02<dmwit>It also gives the programmer a little control for times when the optimizer fails.
05:18:10<dmwit>For people who care about optimization, this matters, too.
05:18:13<amckinley>what i feel like i *should* do is produce a bunch of substrings that correspond to the record boundaries, then pass those strings off to more specific parsers for each record type
05:18:20<amckinley>which isnt very parsec-y
05:18:42<rick_2047>cant i have an or ( || ) condition in a predicate??
05:18:50<dmwit>rick_2047: Sure you can.
05:19:01<dmwit>amckinley: That's perfectly parsecy.
05:19:13<timmaxw>dmwit: we could talk about this for a while but unfortunately i have to sign off. goodnight, and this has been an interesting discussion.
05:19:30<dmwit>amckinley: In fact, it's very much like having a lexer stage (where lexemes are records).
05:20:02<amckinley>dmwit: how could i do something like that? my understanding is that once ive consumed a character, i cant consume it again without invoking parse a second time
05:20:18<dmwit>amckinley: Right... but then you *have* the character. ;-)
05:21:08<sclv>amckinley: also you can simply not use lexeme parsers and parse whitespace explicitly.
05:21:09<dmwit>amckinley: One simple way is to have your first-stage parser return a [String], where each element is a record.
05:21:23<amckinley>dmwit: so is that the way to do it? make a pass over the file to break it up, then make another pass with another set of parsers?
05:21:32<amckinley>er, thats a yes^^ :)
05:21:48<dmwit>amckinley: It's certainly not the only way. But if that way seems natural to you, it's also certainly not a bad way.
05:23:08<amckinley>dmwit: it definitely feels natural, but im using this project (partly) as an excuse to learn haskell and parsec, so if theres a preferred way of doing it, id rather jump through the hoops of learning it :)
05:23:57<dmwit>I see nothing wrong with this way.
05:24:04<sclv>also lookAhead is perfectly fine in moderation
05:24:16<sclv>(i.e. for determining if the next character is a paren)
05:24:22<amckinley>sclv: that was my next question :)
05:24:22<dmwit>sclv means try, not lookAhead. ;-)
05:24:34<sclv>dmwit: no. I mean lookAhead too.
05:25:07<sclv>you can write parsers without it, but sometimes I find it more elegant looking if ever so slightly less efficient to use it.
05:36:07<amckinley>sclv: dmwit: so here's a first crack at the lexer stage; i havent tested it yet, but could you (and anyone else) critique my style? http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5484
05:37:26<sclv>amckinley: return an Either instead?
05:38:23<sclv>or better yet do (parens nlSepList <|> plainList) where those are the two styles..
05:38:36<sclv>and thus skip the lexer stage.
05:39:18<sclv>if parsec hits the first paren it knows its in the first style, and can parse the rest, then throw away the end, and if it hits anything else, then it'll try in the second style.
05:40:06<amckinley>sclv: its actually hard to say whether or not you could legitimately put content on the same line as the closing paren
05:40:32<sclv>amckinley: its easy to write the parser either way tho...
05:40:39<amckinley>the RFC describes the parens as an "ignore newlines between these delimiters" thing
05:40:48<sclv>there's sepBy and sepEndBy...
05:41:13<sclv>ah! i see what you mean...
05:41:17<amckinley>sclv: ive been totally brainlocking on how to use either one of those combinators :P
05:41:53<sclv>so you really want a restOfLine function that will read the rest of the line, or read downward, tossing out parens as it goes.
05:42:01<sclv>but you also need to know how to ignore comments.
05:42:24<amckinley>sclv: exactly
05:43:25<sclv>restOfLine =parens textWithoutComments <
05:43:33<sclv><|> manyTill (char '\n')
05:44:33<amckinley>textWithoutComments seems like a hard thing to write
05:45:07<notsmack>any decent mp3 decoding bindings?
05:45:08<sclv>where textWithoutComments = fmap (intercalate " ") $ many lineWithoutComments
05:45:52<amckinley>touche :)
05:46:02<sclv>where lineWithoutComments = manyTill anyChar (char '\n' <|> (char ';' >> manyTill anyChar (char '\n')))
05:47:17<sclv>I always end up refactoring my parsec parsers quite a bit as I go along, but even more so when I was learning -- its easy to knock something out that works then clean it up later and try to feel out the logic hidden in the grammar.
05:47:53<dmwit>notsmack: Well, there's that "Let's write an mp3 decoder" paper somebody wrote for their master's.
05:48:16<dmwit>http://blog.bjrn.se/2008/10/lets-build-mp3-decoder.html
05:48:28<notsmack>dmwit, hadn't seen, i'll take a look
05:48:48<dmwit>notsmack: I should maybe ask why you want that, though.
05:48:51<amckinley>sclv: im going to try some of this out, back in a minute
05:49:15<dmwit>notsmack: Oh, never mind, you did ask for bindings. =P
05:49:18<notsmack>dmwit, just want to knock a quick music player together
05:49:22<dmwit>notsmack: Have you checked the audio libraries on Hackage?
05:49:40<notsmack>yeah, looked through them a bit
05:49:54<dmwit>ACTION wonders briefly if there is a binding to the mpd stuffs
05:50:21<dmwit>Of course there is!
05:50:41<walter_>Which Lib quite handful to creat HTML file?
05:51:20<notsmack>dmwit, mpd doesn't really suit my needs; i was about to look at rhythmbox or totem via dbus bindings next
05:51:35<dmwit>notsmack: What are your needs?
05:52:03<Cale>walter_: The one called 'html' is probably reasonable, though I haven't really used Haskell to generate much html myself.
05:52:25<dmwit>walter_: WASH has a beautiful DSL for HTML construction.
05:52:26<notsmack>dmwit, well, i want to be able to play a file, not mess with IDs from mpd's music database
05:52:56<dmwit>walter_: There's also html, xhtml, and xml packages on Hackage (by those names, even).
05:53:08<Cale>Hey, is WASH not on Hackage?
05:53:19<dmwit>I wonder if WASH even builds with recent GHCs.
05:53:25<Cale>ACTION doesn't see it there
05:53:33<walter_>yeah, so many lib on html xhtml
05:54:23<dmwit>WASH actually generates correct strict XHTML (guaranteed by the type system!), with a small patch to change the declaration from transitional to strict.
05:54:25<walter_>dev-haskell/wash is in the Gentoo portage overlay
05:54:46<walter_>I will try wash
05:56:34<walter_>Wash is not in Hoogle
05:56:39<dmwit>nope =/
05:56:45<dmwit>But the docs are good.
05:57:00<walter_>dmwit, that's great
05:57:24<dmwit>http://www.informatik.uni-freiburg.de/~thiemann/WASH/#washhtml
05:57:33<MyCatVerbs>dmwit: off the cuff, is there any library you'd specifically recommend for HTML 4.01?
05:57:41<MyCatVerbs>Er, 4.01 Strict, even.
05:58:05<dmwit>I've only ever used the one. =P
05:59:25<Jedai>MyCatVerbs: I would probably use xhtml (it only produce XHTML 1.0 Transitional, Strict or Frameset though)
05:59:49<walter_>dmwit, thanks!
06:01:11<MyCatVerbs>Jedai: I personally prefer 4.01 to xhtml for a couple of bad ideological reasons.
06:01:46<inimino>there aren't many reasons to prefer XHTML at this point
06:02:40<Jedai>MyCatVerbs: Wash seems to have a good generator for HTML4.01, they use types to guarantee a valid output
06:02:51<dmwit>Oh, is it 4.01?
06:02:57<dmwit>I thought it was XHTML.
06:03:12<dmwit>In any case, I remember validating it as "Strict" for whatever it was. =P
06:03:36<Jedai>MyCatVerbs: I never used it though, and the webpage explain that it was thoroughly tested on the 2001 release of Hugs...
06:03:49<dmwit>Yeah, it's a bit old.
06:03:58<Jedai>dmwit: the link you sent say it's 4.01 anyway
06:04:14<dmwit>I trust its docs much more than my memory.
06:05:25<MyCatVerbs>Jedai: oh! I thought dmwit meant it did xhtml only.
06:05:36<dmwit>That's what I meant, but I was wrong.
06:05:37<MyCatVerbs>Sorry, my bad. Checking the website for WASH, yes it does 4.01 as well.
06:08:33<walter_>I got an error while install WASH, it said "Current maximum heap size is 299999232 bytes (286 MB);
06:08:33<walter_>use `+RTS -M<size>' to increase it.
06:08:33<walter_>"
06:08:57<dmwit>Wow.
06:09:17<dmwit>Could you paste the whole output?
06:09:18<dmwit>?hpaste
06:09:18<lambdabot>Haskell pastebin: http://hpaste.org/new
06:09:44<walter_>http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5487#a5487
06:11:40<dmwit>walter_: Is it easy to have a look at the file that failed compilation?
06:11:48<dmwit>I'd be interested in seeing what makes GHC die.
06:12:50<walter_>dmwit, a moment, let me try
06:13:32<Jedai>dmwit: I think it's a problem with the build system somehow... the heap size isn't supposed to be limited by default
06:14:41<Axman6>anyone got any suggestons for interesting some papers to read, possibly about haskell and/or concurrency/parallelism, or techniques for making it faster... or just papers you think are fascinating
06:15:10<MyCatVerbs>Axman6: if you look up the implementation docs for GHC, there's the spineless-tagless-G-machine paper.
06:15:22<MyCatVerbs>Somewhere or other on haskell.org.
06:15:25<Axman6>heh, that sounds fun
06:15:39<MyCatVerbs>If you're looking for more entertainment than theory, look up the cocaine auction protocol.
06:15:46<Axman6>http://portal.acm.org/citation.cfm?id=289439 ?
06:15:50<MyCatVerbs>Possibly the most exciting infosec paper I've read yet.
06:16:19<dmwit>How about that "bidirectionality for free" paper?
06:16:21<MyCatVerbs>Sounds like the right title. Guess I got the author wrong.
06:17:11<mauke>"naturally"
06:29:07<notsmack>anybody used the DBus bindings?
06:29:31<notsmack>ACTION is trying to figure out how to listen for a signal
06:31:31<dmwit>notsmack: Not sure, but maybe addFilter?
06:32:31<walter_>dmwit, http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5489#a5489 the only log I got while install wash
06:33:18<dmwit>walter_: Dunno. Try upping the heap size, I guess?
06:33:18<amckinley>sclv: still around?
06:34:36<walter_>yep
06:34:38<cads>hehehe
06:34:40<cads>hahaha
06:34:43<cads>HAAAAHAHAHAHA!!!!
06:35:34<cads>we can define tuples as sets!
06:35:34<cads>as in the following example : {{a} {a b} {a b c} {a b c d} {a b c d e}}
06:35:46<cads>which is equivalent to (a b c d e)
06:36:04<dmwit>I'm with you so far.
06:36:32<cads>then we can write functions parameterized on tuple types of varying rank
06:36:40<MyCatVerbs>cads: but tuples are more like bags than sets? Sets enforce singularity.
06:36:57<dmwit>cads: But we can already do that, with lists.
06:37:07<dmwit>cads: (Remember, all the elements of the set have to have the same type.)
06:37:11<MyCatVerbs>Er, wrong term, but anyways. Sets enforce that each element is in there at most once.
06:37:12<cads>no!
06:37:24<cads>that's not the definition of sets!
06:37:36<dmwit>cads: Are we talking about Haskell, or not?
06:38:04<cads>aw that crushes me... I though they'd be mathematical sets
06:38:10<cads>not... unordered lists
06:38:28<dmwit>MyCatVerbs: The standard trick is to wrap things in more and more set brackets until they're unique.
06:38:32<cads>ah well
06:39:19<cads>dmwit: it's my long running pie in the sky dream to be able to write a function that can take a tuple of arbitrary size and type
06:39:45<dmwit>cads: But how would you represent the sets you're using to encode tuples above?
06:40:09<dmwit>cads: If you use Data.Set, then each of the elements has the same type, and so you might as well just use an (ordered) list of elements.
06:40:24<dmwit>cads: Also, have you seen HList?
06:40:51<cads>ah
06:40:53<cads>nice
06:40:55<cads>okay
06:41:06<dmwit>(a, b, c, d) is encoded as (a, (b, (c, (d, ())))), with some major type-hackery to make it convenient
06:41:19<dmwit>cads: (Hence my comment above about using lists. ;-)
06:42:25<dmwit>ACTION realizes that there are really two threads of conversation happening here, and they are mildly confusing.
06:42:52<cads>ok yeah, we got to do something like foldl1 . [curry, curry, curry]
06:42:53<dmwit>(a, b, c, d) is encoded that way in HList. There, I hope I've disambiguated.
06:43:05<dmwit>cads: doesn't type-check
06:43:26<dmwit>cads: Curry is being used at different types there, you'll get an occurs-check errror.
06:43:37<dmwit>> foldl1 (.) [curry, curry, curry]
06:43:38<cads>oh right
06:43:43<lambdabot> mueval-core: Prelude.read: no parse
06:43:43<lambdabot> mueval: ExitFailure 1
06:44:16<dmwit>:t foldl1 (.)
06:44:23<lambdabot>forall b. [b -> b] -> b -> b
06:44:25<dmwit>:t foldr (.) id
06:44:27<cads>well, I think the HList is exactly what I'd need for anything I'd use 'dynamic tuple functions' for
06:44:32<lambdabot>forall a. [a -> a] -> a -> a
06:44:58<cads>but then there's the problem of how you actually write a function that uses values inside an hlist, but i'd like to see what kind of interface it gives for that
06:45:08<dmwit>http://okmij.org/ftp/Haskell/types.html
06:46:36<walter_>since I can not install WASH, will try HStringTemplate instead
06:46:50<rob__>Hi all, I have a quick question: is it possible to instantiate a type constructor in a type class?
06:47:03<dmwit>walter_: Smart move. =P
06:47:14<dmwit>rob__: Only if the kinds match.
06:47:20<walter_>dmwit, :)
06:47:52<walter_>Someome's advice: http://blog.uncommons.org/2008/12/03/generating-html-with-haskell/
06:48:16<rob__>dmwit: how can i find out if they match?
06:49:12<dmwit>rob__: You can use :k in ghci to find the kind of a type constructor (even if partially applied).
06:49:31<dmwit>rob__: As for what kind it has to be for the instance... that you can usually do by inspection of the instance.
06:49:41<rob__>dmwit: thanks I'll try that
06:49:47<dmwit>rob__: (You can mostly find the kind of a type constructor by inspection, too. =)
06:49:54<dmwit>rob__: Can I ask what this is about?
06:50:00<ray>haskell kinds are pretty simplistic
06:50:02<dmwit>rob__: If you give us more details, we can help you more.
06:50:31<vininim_>:t liftM2
06:50:38<lambdabot>forall a1 a2 r (m :: * -> *). (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
06:50:47<ray>:k ReaderT
06:50:53<vininim_>:t liftM2 (,,)
06:50:55<lambdabot>* -> (* -> *) -> * -> *
06:51:02<lambdabot>forall a1 a2 c (m :: * -> *). (Monad m) => m a1 -> m a2 -> m (c -> (a1, a2, c))
06:52:04<rob__>dmwit: sure I'm trying to write yet another ray tracer as an exercise and I defined some objects as type constructors in a datatype and I made a type class to define common functions for them
06:52:40<dmwit>Are you sure what you're talking about are actually type constructors and not value constructors?
06:53:02<dmwit>(This is a common mistake, sorry if this is totally obvious to you.)
06:54:00<dmwit>:k Monad m => m a
06:54:07<lambdabot>*
06:54:10<dmwit>lambdabot++
06:54:34<ray>:k Monad m => m
06:54:40<lambdabot> `m' is not applied to enough type arguments
06:54:40<lambdabot> Expected kind `*', but `m' has kind `* -> *'
06:54:48<ray>it told me, sorta
06:57:20<rob__>dmwit: oh good catch, I got those confused
06:58:18<ray>if so, then you probably want a function, not a class
07:00:32<rob__>is there no way to do class Object Plane where ... for data Objects = Plane ...?
07:03:17<dmwit>rob__: You may be a little confused about what class means.
07:03:25<dmwit>It doesn't mean the same thing in Haskell that it does in other languages.
07:03:49<dmwit>In Haskell, a "class" is a collection of types, and some operations that work on those types. Nothing more, nothing less.
07:04:07<dmwit>If you have a data declaration, that creates one single type; not much sense creating a class just for that one type.
07:04:17<bos>@let m n = if n > 200000 then n - 20000 else m (m (n + 20001))
07:04:20<lambdabot> <local>:7:40:
07:04:20<lambdabot> Ambiguous occurrence `m'
07:04:20<lambdabot> It could refer to either `L...
07:04:27<rob__>so would I have to define a new data type for every object then?
07:04:42<bos>@let eff n = if n > 200000 then n - 20000 else eff (eff (n + 20001))
07:04:58<lambdabot> Defined.
07:05:05<bos>> eff 2
07:05:11<lambdabot> mueval-core: Prelude.read: no parse
07:05:11<lambdabot> mueval: ExitFailure 1
07:05:18<dmwit>rob__: I'm not even sure I understand your question.
07:05:21<dmwit>rob__: What is an object?
07:05:25<bos>huh.
07:05:35<bos>> eff (222::Int)
07:05:42<lambdabot> mueval-core: Prelude.read: no parse
07:05:42<lambdabot> mueval: ExitFailure 1
07:05:50<rob__>oh by object I just meant a sphere, plane, torus etc...
07:05:53<bos>lambdabot--
07:06:14<ray>@thump
07:06:14<lambdabot>Unknown command, try @list
07:06:45<dmwit>rob__: I expect you'd have a single data type for shapes, and spheres, planes, toruses, etc. would simply be values of that type.
07:07:02<dmwit>rob__: But I can't say for sure, as I don't know the problem space very well.
07:09:24<rob__>dmwit: that's what I was doing, but I wanted to implement an intersect function for each one of them, so I tried using a type class and make each object an instance of it
07:16:26<edwardk>ACTION waves hello.
07:16:58<dmwit>Hiya, edwardk!
07:17:11<dmwit>Are you coming to Hac Phi?
07:17:21<edwardk>Looks highly probable
07:17:32<dmwit>awesome!
07:18:03<dmwit>I look forward to days of type hackery. =D
07:18:09<edwardk>I may drag a statistician friend of mine who is doing some work on the hbc BUGS model compiler, and see if we/he can interest folks in helping out on that project
07:18:45<dmwit>hbc?
07:19:00<edwardk>http://www.cs.utah.edu/~hal/HBC/hbc.pdf
07:19:00<dmwit>Whoa, this?
07:19:04<dmwit>http://www.cs.chalmers.se/~augustss/hbc/hbc.html
07:19:15<edwardk>the other one
07:19:27<dmwit>Okay, your link looks a lot more recent than mine. =)
07:19:28<edwardk>I've been teasing Aleks that he should try to get Hal to change its name =)
07:20:10<dmwit>Ah, this looks pretty cool.
07:21:38<FERRET_SWAMI>haskell whats up folks
07:21:45<FERRET_SWAMI>seems like a rpetty exciting lang you all have here
07:22:01<edwardk>Personally, I'm interested in updating the interpreter that has fallen into disuse to include the current feature set of the compiler and in looking into what can be done to distribute the model over the network, etc.
07:22:44<edwardk>That, and seeing if some/all of the surface language could be rewritten into just an EDSL for haskell rather than a traditional compiler model.
07:23:02<edwardk>that would allow for the use of haskell to provide higher order tools for model specification.
07:23:13<edwardk>FERRET_SWAMI: we're fond of it =)
07:23:53<FERRET_SWAMI>paul graham site said he was disappointed with staatic typing
07:23:55<FERRET_SWAMI>languages
07:24:09<Twey>Paul Graham says a lot of things
07:24:09<FERRET_SWAMI>can haskell let em write programs bit by bit
07:24:14<FERRET_SWAMI>me-
07:24:16<Twey>Yes
07:24:28<FERRET_SWAMI>for example a program to monitor a website I build
07:24:31<edwardk>paul graham also has a nice little law in which he points out that 'no one sees the point in any language more powerful than his own' it seems he is somewhat hoist on his own petard in that regard ;)
07:24:34<FERRET_SWAMI>using snmp
07:24:39<Twey>edwardk: Heheheh
07:24:43<p_l>FERRET_SWAMI: Yes, it can, though I miss Lisp-style development
07:24:55<FERRET_SWAMI>I have 2 or 3 haskell book
07:25:01<FERRET_SWAMI>but when I see -->
07:25:04<p_l>edwardk: that would be the matter with Arc, I guess. It became a laughing matter in Lisp circles as well :P
07:25:15<FERRET_SWAMI>and stuff I feel like I missed some prereq class..
07:25:22<FERRET_SWAMI>can I learn programmign from scratch with ahskell?
07:25:35<sjanssen>edwardk: yes, I always found his talk about "blub" ironic
07:25:35<edwardk>i like the idea of arc, i've even stolen some ideas from it in my toy compilers, but yeah
07:25:50<p_l>FERRET_SWAMI: I guess you can, though the way of programming would be slightly different than let's say C
07:25:59<FERRET_SWAMI>haskell one thing I like is that it can utilize many cpu
07:26:01<FERRET_SWAMI>right?
07:26:11<FERRET_SWAMI>I never learned c
07:26:13<FERRET_SWAMI>..
07:26:18<FERRET_SWAMI>I have the k+r book
07:26:35<FERRET_SWAMI>plan9 people even told me that c can be quite high level with file abstractions
07:27:09<edwardk>FERRET_SWAMI: haskell can work nicely on multiple cpus because it carefully controls the side effects of code, so you can know how multiple threads will interact in ways you can't with a more traditional language
07:27:10<Twey>That's not making C high-level
07:27:19<p_l>FERRET_SWAMI: They are right, but C is different - it's more like portable assembler, frankly speaking. But steer away from C++ :D
07:27:31<Twey>That's using existing C interfaces to interact with a high-level system
07:27:37<edwardk>FERRET_SWAMI: plan9 just makes everything into a file. if you only have a hammer...
07:27:44<FERRET_SWAMI>llol
07:27:56<FERRET_SWAMI>happstack looks liek cool website tool
07:28:17<edwardk>don't get me wrong, its an incredibly general interface, but not everything can be cleanly mapped onto the file abstraction, nor necessarily should it
07:28:19<FERRET_SWAMI>I have booko by hutton an antoher bybhudak
07:28:33<FERRET_SWAMI>haskell is super 'high level'
07:28:36<FERRET_SWAMI>I hear
07:28:38<edwardk>FERRET_SWAMI: i'd recommend two sources. Learn You a Haskell for Great Good, and Real World Haskell.
07:28:50<FERRET_SWAMI>does this really make it way more fun than popular langs liek ruby
07:28:53<Twey>FERRET_SWAMI: Well
07:28:53<FERRET_SWAMI>ok
07:28:58<edwardk>Real World Haskell will dispel the 'super high level' myth to some extend, and Learn You a Haskell is very accessible.
07:29:02<Twey>It's kind of high-level, and kind of low-level.
07:29:02<edwardk>er extent
07:29:17<Twey>It's quite far away from the hardware (by default)
07:29:33<Twey>But in terms of language and mathematics, I'd say it's closer to its foundations than C
07:29:38<edwardk>to me what i like about haskell is that it is the best language i've found to 'think in'.
07:29:52<FERRET_SWAMI>think in
07:30:11<FERRET_SWAMI>functional you try to jsut think about howto compute the asnwer you want
07:30:15<FERRET_SWAMI>like my bank balance
07:30:18<edwardk>Its my own personal Blub. I don't see the point of those weird dependently typed languages in which you can never seem to get anything done, and I don't like less powerful languages because they are missing so many features I'm used to.
07:30:23<FERRET_SWAMI>or order for 4 new cool t shirt
07:30:35<FERRET_SWAMI>hmm
07:30:38<FERRET_SWAMI>hmmmmmmmmmm
07:30:47<jeffwheeler>That makes me think we need Haskell shirts that don't suck.
07:31:11<FERRET_SWAMI>now what about the schuette problem: 95% of servers at load avg 0.3 while 5% of servers at load avg 17
07:31:17<dmwit>edwardk: heh, I like that
07:31:34<dmwit>Managers rise to their level of incompetence, programmers rise to their level of Blub. =)
07:31:43<edwardk>dmwit: heh
07:31:50<FERRET_SWAMI>"once you go hask, you never go back!: haskell.org"
07:32:10<Twey>ACTION twitches.
07:32:16<edwardk>well, I generally just look at what I can get done in a weekend in Haskell, and then I compare it to what a good Coq developer can get done, he won't have finished trying to figure out what he's trying to say yet ;)
07:32:22<FERRET_SWAMI>the dream of business people is apps on commodity hardware that are immune to failure
07:32:44<p_l>FERRET_SWAMI: No, the dream of business people is clients who have money and no brains
07:32:57<dmwit>Immune to failure?
07:33:01<dmwit>That sounds tricky.
07:33:07<FERRET_SWAMI>uh oh, looks like I thought wrong, again
07:33:07<dmwit>ACTION pulls the plug and shoots the UPS
07:33:16<FERRET_SWAMI>well somehow you have 40 servers
07:33:18<edwardk>p_l: i'm fond of clients with both money and brains, its easier to reason with them, and you can make them more profitable more easily so they keep coming back to you for more.
07:33:24<FERRET_SWAMI>and the app adjsuts if 3 die
07:33:29<FERRET_SWAMI>and notifies you
07:33:38<edwardk>FERRET_SWAMI: then you probably want Erlang ;)
07:33:44<FERRET_SWAMI>mogileFS I think by danga interactive is a huge step
07:33:47<p_l>edwardk: that's rare, the big players want idiots :_
07:33:50<p_l>*:P
07:33:54<edwardk>they've been doing that sort of thing for years =)
07:34:04<FERRET_SWAMI>Im amazed how much idiots pay for 'managed' hosts
07:34:06<FERRET_SWAMI>hosting
07:34:13<FERRET_SWAMI>'managed hosting'
07:34:30<FERRET_SWAMI>erlang, hmm, erlang....I heard its nice
07:34:36<FERRET_SWAMI>even has a webserver yaws
07:34:38<Twey>It's not nice
07:34:43<Twey>It's a horrible language
07:34:47<edwardk>FERRET_SWAMI: its not all that idiotic to focus on your core competencies and farm out the rest, specialization is one path to suceess.
07:34:51<Twey>But it is built on some nice concepts
07:35:34<Twey>I agree with edwardk
07:35:43<Twey>People with brains are much nicer to work for than people with no brains
07:36:23<p_l>Twey: to work for. Hearing some of "big industry" (not necessarily computer industry) heads talk, I think they want cattle
07:36:29<jeffwheeler>ACTION likes Cabal's new warning about the package index being more than 15 days old or so
07:36:40<dmwit>The nicest part is when they succesfully identify the clever solution to a hard problem. =D
07:36:48<edwardk>I like the idea of erlang, but perhaps I'm a language bigot. I want some types and I miss laziness and its slightly better asymptotics too much. And I much prefer constructors with variable arities and Haskell's partial applicative style to the prolog full application style
07:36:59<Twey>ACTION nods.
07:37:24<dmwit>jeffwheeler: Boy howdy!
07:37:33<p_l>edwardk: well, my policy is to learn a few good tools and then use "choose best tool for the job" way :)
07:37:41<jeffwheeler>dmwit: your work? :)
07:37:56<dmwit>jeffwheeler: Nope, I just totally agree with you!
07:37:58<dmwit>Cabal rocks!
07:38:04<jeffwheeler>Ah, yep.
07:38:23<edwardk>p_l: yeah. i'm glad i added haskell to my toolbox, though i seriously took a left turn somewhere and it became more of the focus of my research than the means ;)
07:38:36<jeffwheeler>The whole system kicks the pants off of those for other languages . . . Python's mess of installation tools comes to mind.
07:40:14<dmwit>It helps that our main implementation started out with a pretty sane packaging system.
07:40:27<hackagebot>minesweeper 0.4
07:40:34<dmwit>Minesweeper??
07:40:42<dmwit>?hackage minesweeper
07:40:42<lambdabot>http://hackage.haskell.org/cgi-bin/hackage-scripts/package/minesweeper
07:40:46<jeffwheeler>ACTION installs.
07:41:00<edwardk>my biggest fear for hackage/cabal is the 'layering problem', which is more of a language design/library feature interaction issue. its hard to layer in new abstractions, because if you have a suitably large non-trivial library that introduces new instances for a lot of existing code, you can't split it in a way that makes it palatable to push all of the instances down into the source libraries without making orphan
07:41:04<p_l>dmwit: that's true. On Lisp, the last sensible package manager I had seen was for Genera, I think :D
07:41:06<FERRET_SWAMI>I heard darcs got beat up for performance problems
07:41:11<edwardk>so there is a 'new abstraction tax' inherent in the language that bugs me
07:41:20<FERRET_SWAMI>and mercurial and git are these really good code lockup tools
07:41:49<FERRET_SWAMI>is darcs no longer considered a competitor?
07:41:55<FERRET_SWAMI>in the source safe wars
07:42:12<MyCatVerbs>FERRET_SWAMI: depends on how large your repositories are, mostly.
07:42:15<edwardk>FERRET_SWAMI: i prefer darcs over git for my personal projects, because its so much nicer to be able to pick and choose bits and pieces of patches in darcs, but git does seem to work in the large well.
07:42:23<Beelsebob1>darcs is an excellent compettitor still, as long as you only have small to medium sized repos
07:42:34<Beelsebob1>Mercurial I've found horibly unreliable
07:42:50<edwardk>what i like about darcs is that when i'm working on a 1-3 developer project, darcs just slots right into the work flow and gets out of the way.
07:42:52<MyCatVerbs>I still use darcs myself, but friends of mine have switched over to Mercurial, and the GHC project switched to Git because of darcs' performance issues.
07:43:01<edwardk>and i'm never messing around dealing with messy merges, etc.
07:43:13<dmwit>No other system beats darcs' UI yet.
07:43:26<edwardk>ghc also has to deal with ~10 years of history or something crazy like that
07:43:28<cads>git's cola is not a bad ui
07:43:43<MyCatVerbs>Mmmmmost of darcs' problems don't come up until you get to a fairly large quantity of code.
07:43:52<cads>rather, cola for git
07:44:31<FERRET_SWAMI>good night all
07:44:36<jeffwheeler>That minesweeper game is great.
07:44:43<edwardk>the main thing i like about darcs is that i just sort of initialize the repository and i don't think about it until its saving my ass
07:44:57<maxote>darcs' performance issues can be improved if the GHC's performance issues are solved
07:45:00<jeffwheeler>I love the probabilities features.
07:45:14<edwardk>jeffwheeler: the oz thing?
07:45:34<jeffwheeler>edwardk: C-p in the minesweeper package on Hackage that was just updated
07:45:59<jeffwheeler>edwardk: it shows the probabilities that each square might contain a mine, given the revealed locations.
07:45:59<edwardk>ah
07:46:09<edwardk>ok, so the same idea
07:46:27<dmwit>uh-oh
07:46:35<dmwit>I accidentally ln -s something .
07:48:09<sjanssen>maxote: darcs issues at this point don't really have anything to do with the compiler
07:51:55<dmwit>Hey, this minesweeper game is really cool!
07:52:37<dmwit>jeffwheeler: Try focusing another window while you're playing.
07:53:48<jeffwheeler>dmwit: you mean that it pauses?
07:54:13<dmwit>yep
07:54:18<jeffwheeler>The default GNOME Minesweeper does that, but I'm impressed with the 'lucky' stuff at the top.
07:54:22<dmwit>But just in general the idea is totally rad.
07:54:31<dmwit>Guaranteed no guessing.
07:54:40<dmwit>If you die, it's because you didn't reason well enough. =)
07:54:43<jeffwheeler>I'm not that good, though. ;)
07:54:49<dmwit>ACTION is
07:55:00<dmwit>More importantly
07:55:04<jeffwheeler>I'm trying to learn, based on its probabilities.
07:55:06<MyCatVerbs>dmwit: IIRC there's a paranoid version of Minesweeper too.
07:55:07<dmwit>ACTION 's mother is
07:55:30<MyCatVerbs>Where the game plants a mine under the cursor whenever it's possible for a mine to be there.
07:55:33<dmwit>MyCatVerbs: What, it always kills you if it can?
07:55:37<dmwit>ACTION nods
07:55:39<dmwit>jerks
07:55:46<MyCatVerbs>Aye.
07:56:19<jeffwheeler>It must be very difficult to start that game. ;)
07:56:47<jeffwheeler>(Alternatively, that could make it very easy to program.)
08:02:46<dmwit>yipe!
08:03:00<dmwit>It gets a little slow if you guess randomly a lot at the beginning. =P
08:05:39<MyCatVerbs>Heh.
08:06:01<cads>http://projectfortress.sun.com/Projects/Community/wiki/FortressQuestions#InwhatwaysdoesFortresssyntaxresemblemathematicalnotation
08:06:07<cads>oh my god
08:06:16<cads>I want to code in that.
08:06:58<cads>except... those semantics look imperative ...
08:08:29<flux>cads, but here clearly is a difference between bindings and assignments
08:08:45<cads>ah, very very true!
08:08:59<cads>I missed right over that
08:09:55<flux>haven't heard of Fortress much since it was announced
08:10:09<cads>nope
08:10:22<cads>people are commiting code to it though
08:10:45<cads>I think they lost their funding and now it's just an open project
08:11:05<cads>I'm trying to find a mailing list or something
08:11:20<cads>the whole rendering to tex thing is fucking supreme.
08:12:01<cads>something that's been really souped up like that could be pretty nice for haskell
08:12:29<cads>the day I see an integral symbol in computer code will be a happy day
08:12:42<rick_2047>well in there general forums there is only one topic and that too 2 years old
08:12:49<MyCatVerbs>There's TeX style literate Haskell notation, though that doesn't do much for you.
08:12:51<dmwit>Well, Agda uses Unicode.
08:13:03<dmwit>So you can get the integral symbol if you really want it.
08:13:25<rick_2047>cads, http://research.sun.com/projects/plrg/faq/index.html#twelve <-- here is your mailing list
08:13:50<ray>it's true, haskell should look like that
08:14:31<MyCatVerbs>ray: excuse me if I take a sliiiightly derisory view of combinators whose names are difficult to type on any keyboard that I own.
08:15:14<cads>rick_2047: thanks bud :)
08:15:49<rick_2047>cads, your most welcome
08:16:13<ray>monospaced code listings are so 1970s
08:16:37<cads>MyCatVerbs: you'd type \special_shit_{underscript}^{overscript}_subscript^superscript (function args) 3 beers a cigarette some pizza
08:17:09<cads>you you have to touch tex, that is
08:17:15<ray>i was thinking more "a fancy editor" than "write it in latex" myself
08:17:32<ray>if it doesn't look pretty while you're entering it what good is it
08:17:37<cads>I think this has special rules for turning it pretty
08:17:42<MyCatVerbs>cads: aye, but that's TeX notation (which I'm happy with), rather than putting Unicode characters right in (which is a pain in the unmentionables, for the moment).
08:18:12<MyCatVerbs>cads: ray suggested the latter, so I went "bletch!".
08:19:13<cads>a generic way of mapping tex to various programming semantics would be neat
08:19:28<cads>I wouldn't mind writing code in renderable tex
08:19:39<cads>as long as well written programs would typeset well :)
08:20:08<QtPlaty[HireMe]>Well TeX is turing compleate.
08:20:15<cads>I'd be killing two birds with one stone, coding and documentation
08:20:26<ray>you just need a fancy editor
08:20:30<ray>emacs could probably do it
08:20:32<MyCatVerbs>SCIM has a mode that lets you put unicode maths characters in by giving their TeX names, but it was a pain in the arse last time I tried to set it up, and it's kind of incomplete.
08:20:40<cads>QtPlaty[HireMe]: sure, but the symbols don't have any semantics of their own
08:21:02<MyCatVerbs>Plus, it wouldn't work anywhere near Windows, which is a bit of a problem too. (And that's me saying that as a diehard Unix goon.)
08:21:35<MyCatVerbs>QtPlaty[HireMe]: not only that, but TeX is deliberately Turing-complete several times over. :)
08:21:47<cads>when you say \sum_{a in E} a^2 in tex you're not telling it to "sum the square of every element in E", you're telling it to gorgeous-print the summation symbol
08:21:55<MyCatVerbs>QtPlaty[HireMe]: IIRC, at least two different phases of TeX are both Turing complete, and it's deliberate too.
08:22:45<cads>MyCatVerbs: really? where could I read about this?
08:23:25<cads>does tex have the stuff it would take to emit executable code in another language as a side effect of printing its symbols?
08:23:55<cads>heh, would we want to code that system in tex, in other words
08:24:03<ray>ouch
08:24:16<dmwit>cads: Oh, that's easy, the answer to that one is no.
08:24:41<ray>tex has what it takes to emit tex, i think
08:25:25<cads>that's what I thought too
08:25:47<ray>i doubt it can really emit, say, ELF
08:25:48<cads>ACTION remembers getting lost in the directory trees of tex macros for writing papers
08:26:54<ray>anyway, haskell source should look like the output of tex, not the (hideous) input
08:27:30<cads>working with that kind of format is pretty hideous in itself
08:27:46<cads>have you ever tried to seriously edit a typeset equation in mathematica?
08:28:13<ray>i don't claim that a sufficiently smart editor exists
08:28:16<ray>just that it's not impossible
08:28:33<ray>maybe it's impossible with current input devices :)
08:29:49<cads>well in mathematica you have a palette of symbols that you can click on, and once you've inserted say an integral sign, then putting your mouse directly over or beneath it highlights a box that you can click on to put in symbols on top or below the integral
08:29:57<rick_2047>where can i have a look into the base libs of haskell??
08:30:06<dmwit>?where hhl
08:30:07<lambdabot>I know nothing about hhl.
08:30:08<ziman>rick_2047, http://www.haskell.org/ghc/docs/latest/html/libraries/
08:30:12<dmwit>?where hierarchical
08:30:12<lambdabot>I know nothing about hierarchical.
08:30:15<dmwit>damn
08:30:49<cads>ray, that's pretty simple, but there's no way to enter code quickly that way, it's purely for final typesetting
08:31:03<rick_2047>ziman, i meant there source
08:31:13<rick_2047>ziman, i am presuming that they are written in haskell itself
08:31:27<cads>well I take that back, sometimes I build up integrals and stuff using pretty equations
08:31:53<ray>yeah, i was thinking more emacs
08:32:39<cads>but mathematica code is written like Integral[x^2, {x,-1,1}], and then that can both be evaluated to yield zero in this case, or a typeset integral equation
08:33:11<ziman>rick_2047, choose a lib, click it, scroll down the page and there you'll have a "Source" link on the right, at every function
08:33:31<rick_2047>ziman, isnt it included in /usr/lib/ghc??
08:33:44<rick_2047>ziman, are they all executables of some type?/
08:33:47<cads>emacs would be good as it would get you away from the temptation to make people write things using their mouse :)
08:34:20<ziman>rick_2047, yes i've got a copy in file://localhost/usr/share/doc/ghc-6.10.1/libraries/index.html
08:35:45<ray>pretty-entry shouldn't have to mean mouse
08:35:52<cads>hmm, perhaps the trick is to write haskell code that emits tex as a side effect
08:36:02<rick_2047>ziman, arent there any plain text files just of the source and some comments, dont want this web page crap
08:36:29<cads>and then lets you edit the tex rendered equations
08:36:33<ziman>rick_2047, i've already described how you get to the source
08:37:04<ray>if you do some just-in-time conversion of your expressions to tex, you can render them
08:37:07<ray>or something
08:37:07<sjanssen>rick_2047: http://darcs.haskell.org/packages
08:37:10<cads>wait, the haskell code wouldn't emit the tex, whatever you were using for this exercise would do it
08:37:13<Athas>How do I force the complete evaluation of a term?
08:37:27<cads>ray, yeah
08:38:02<cads>and I think we could bind positions in the rendered tex to positions in the code, and allow bidirectional editing
08:38:09<sjanssen>Athas: evaluation to WHNF is via seq, NF can be achieved with Control.Parallel.Strategies.rnf
08:38:21<ray>if your computer is fast enough, and people tend to lug around these multi-core gigglehertz behemoths these days, you can basically type in rendered tex
08:38:38<Athas>sjanssen: thanks.
08:39:21<cads>god what I would give for read access to the mathematica code tree
08:39:56<ray>tell wolfram you'll give him some fancy cellular automata in exchange
08:40:10<cads>would that be wolfram speak for a blowjob?
08:40:22<cads>because I don't think I want the code that much
08:40:59<cads>wolfram is nuts :)
08:43:07<cads>thinks the universe is cellular automata and stuff
08:43:07<ray>i have his doorstopper
08:43:07<ray>and by doorstopper, i mean garage door stopper
08:43:07<rick_2047>cads, well even though he is selfrighteous and cocky but he knows how to do things
08:43:07<cads>oh I got some respect
08:43:07<rick_2047>cads, u should me too not a big fan but the things he makes force me to respect him
08:43:07<cads>gonna start a company with my last name and all that some day
08:43:30<rick_2047>whats ur age??
08:43:50<cads>well, I mean, he was a professor, starting a company, used code his students wrote with him
08:44:07<cads>academia type, politically savvy
08:44:22<rick_2047>i sometimes like the path he took
08:44:23<cads>just something I don't like about those kinds of people
08:44:35<cads>the path of industry you mean?
08:44:40<mgsloan>I agree, I have utmost respect for his products, but the man is a douche
08:45:03<rick_2047>cads, the path of industry through academia
08:45:07<mgsloan>reading a good portion of NKS convinced me of that
08:45:15<rick_2047>it shows people the value of academia
08:45:18<cads>and they're not even _his_ products, they're the work of countless developers most likely, and they just bear his name
08:45:40<rick_2047>cads, he has done his work in the field
08:45:49<cads>sure
08:46:20<cads>there were others too, and I don't know their name or their work
08:46:34<cads>I don't know him because of his work, but from his company
08:46:45<rick_2047>cads, that also sticks in my craw
08:46:58<rick_2047>he never gives creadit u know
08:47:25<cads>why should he, he's wolfram
08:48:16<cads>as far as i'm concerned computer algebra systems should be farther along than they are now
08:48:25<sohum>is there a screenplay for a thriller where the climax happens when a frantic haskell programmer is asked by his tormentor to calculate the fibonacci sequence and ends up launching nuclear missiles?
08:48:29<sohum>"Damn yoooooooou, unsafePerformIO! I thought this code was puuuuuuuure!"
08:48:30<rick_2047>u know if u google a quote (i dont remember exactly) but it invovles "wolfram created mathematica" google will correct u " did u mean wolfram created mathematics?"
08:49:23<mgsloan>I think mathematics should follow some functional stuff, and use more things like streams
08:49:35<mgsloan>indices as used in summation etc, are soo ugly
08:50:37<Berengal>mgsloan: Wouldn't that mean we need to teach high-schoolers induction?
08:50:52<quicksilver>ACTION learnt induction at high school.
08:51:03<rick_2047>Berengal, we are taught basic theory of induction in high school
08:51:05<cads>rick_2047: rofl
08:51:06<ski>indices is just another notation for function arguments
08:51:10<mgsloan>so did I :) but yes, it would be good
08:51:14<cads>@wolfram joke
08:51:14<rick_2047>Berengal, very basic though
08:51:15<lambdabot>Unknown command, try @list
08:51:28<rick_2047>cads, its true
08:51:36<rick_2047>cads, wait i find out the quote
08:51:56<Berengal>rick_2047: Well, I did too, in its basic form, but I was doing indexing long before that
08:52:22<ray>@quote wolfram
08:52:22<lambdabot>No quotes match. :(
08:55:23<cads>what's the haskell off topic chan
08:55:23<rick_2047>and they are back
08:55:23<ray>-blah
08:55:23<cads>h-chan if you will
08:55:23<rick_2047>ray, nice name
08:55:23<ejt>qualified bashing: I wish the 'qualified' keyword came after the module name, so I could sort my lines
08:55:23<juhp>hmm pandoc s5 doesn't seem to display well in chromium
08:55:23<Berengal>I want two types of export lists for modules: One that gets imported when no import list is given, and one of functions that can only be imported when explicitly told to
08:56:26<dibblego>cads, #haskell-blah
08:56:29<quicksilver>Berengal: the supported way to do that is do make another dummy module
08:56:37<quicksilver>Berengal: for the 'default' set.
08:56:42<quicksilver>which just imports + re-exports.
08:56:58<quicksilver>However there are some ways in which re-exporting is not very satisfactory.
08:56:58<Berengal>quicksilver: But that's ugly, no?
08:58:43<Berengal>Hmmm, "module Foo (foo, bar, baz) hiding (quux, fuxsputzle) where"
08:58:46<ray>not exactly pretty
08:58:52<ray>better
09:01:03<quicksilver>Berengal: I don't think it's particularly ugly.
09:01:12<quicksilver>Berengal: it's a broadly similar amount of typing.
09:01:14<Berengal>It'd also be nice to be able to enter a package in ghci, analogous to entering a module
09:01:39<quicksilver>it's mildly annoying to have a separate file but that's all
09:01:46<quicksilver>Berengal: packages don't have source
09:01:55<walter_>I am trying HStringTemplate code from http://blog.uncommons.org/2008/12/03/generating-html-with-haskell/, but I got a parse error. http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5492#a5492
09:02:06<Berengal>quicksilver: No, but they have modules, which can be hidden
09:03:14<doserj>walter_: let template = ... instead of template = ...
09:03:41<quicksilver>Berengal: oh, I see what you mean. Yes.
09:04:00<dibblego>how would you pronounce (***) :: (Arrow a) => a b c -> a b' c' -> a (b, b') (c, c') ?
09:04:55<Berengal>dibblego: "foo, of type, a is an arrow in a b c gives a b c gives a b b c c"
09:05:02<codolio>(***) is the action of the product bifunctor on morphisms.
09:05:03<dibblego>I mean the function name
09:05:17<Berengal>foo
09:05:20<dibblego>heh
09:06:03<walter_>doserj, after add let , got another error : test.hs:6:62: Not in scope: `template' http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5492#a5493
09:07:50<doserj>walter_: yes. template is not in scope in the 'where'. try making that a let to
09:08:07<quicksilver>I pronounce it star-star-star
09:08:16<quicksilver>I'm not sure if there should be a cleverer way.
09:08:25<dibblego>ok cheers
09:08:26<ski>star-thrice
09:08:51<walter_>doserj, thanks
09:10:23<Peaker>quicksilver: vertical arrow composition?
09:11:37<ray>i convert punctuation operators like that to grunts in my internal vocalizer
09:11:44<ray>they're all the same grunt because i guess it only does lexing
09:12:00<quicksilver>not unreasonable but I'd have to spend a few seconds each time remembering which way vertical was ;)
09:12:00<ray>so, it's pronounced *grunt*
09:12:54<Peaker>quicksilver: the arrows are always drawn horizontal :)
09:22:46<walter_>help please! Ambiguous type variable error: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5492#a5494
09:23:59<walter_>how to fix it by add type signature
09:24:30<doserj>walter_: let template = (newSTMP templateText :: whatever_your_type)
09:24:55<ski>or
09:24:57<ski> let template :: Stringable a => StringTemplate a; template = newSTMP templateText
09:25:27<walter_>got, thank you both.
09:29:20<poucet>Am I the only one that finds it appalling that jonharrop owns "haskell-news.blogspot.com" where he mostly reports on negative things and then has a bunch of links to f# and ocaml books of his?
09:30:04<quicksilver>there are many things about jdh which sometimes appal
09:30:17<poucet>Disgusting
09:34:48<walter_>doserj, ski, still doesnt work. http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5492#a5496
09:35:44<doserj>let template = (newSTMP templateText::Stringable a) doesn't work because it simply doesn't have this type.
09:36:13<doserj>try let template = (newSTMP templateText::StringTemplate String) or sth similar.
09:36:31<ski>`Stringable a' isn't a type
09:36:42<walter_>I see
09:36:49<doserj>let template :: Stringable a => StringTemplate a doesn't work, because you also need to give a definition for template.
09:36:59<doserj>try let template :: Stringable a => StringTemplate a; template = ...
09:37:08<walter_>This work: let template = (newSTMP templateText::StringTemplate String)
09:37:21<walter_>thanks, doserj
09:37:24<ski>(doserj : which was what i suggested above :)
09:37:58<doserj>(ski: I know :)
09:38:26<ski>walter_ : btw, why are you entering this into GHCi, instead of into a file, as you seemed to try before ?
09:39:16<walter_>ski, because I the demo code doesn't work, and I want to find why.
09:39:50<walter_>this is the demo code from http://blog.uncommons.org/2008/12/03/generating-html-with-haskell/,
09:40:42<walter_> let template :: StringTemplate String
09:41:21<ski>(walter_ : i would try binary search, instead of trying to enter the code in GHCi)
09:42:16<walter_>Infact, I am very green on Haskell. Just want do that step by step to understand. :) thank you.
09:42:50<ski>(i.e. binary search debugging)
09:43:45<walter_>ski, I still have no idea on debugging, btw how to do binary search
09:45:33<ski>comment out about half the code (making sure not to comment out code which the non-commented-out code depends on, optionally instead making stubs); if still error, repeat on non-commented-out code; otherwise; flip what is commented-out and repeat
09:46:55<ski>(btw, generally, if you get actual static error messages, that provides you with hopefully-not-too-far-off file positions from which to look for an error)
09:50:05<walter_>ski, thank you very much.
09:50:51<cads>hey, ski, I always wonder, what's the ski combinator do?
09:51:18<cads>i've looked it up multiple times I'm sure, but either couldn't get it or it was so basic I subsequently forgot it
09:51:39<dolio>@type ap const id
09:51:45<lambdabot>forall b. b -> b
09:51:57<hackagebot>explicit-sharing 0.5.0
09:52:00<cads>oh it's the whole combinator calculus
09:52:47<dolio>s and k are all you need, technically. You can define i in terms of them.
09:53:08<cads>aaaah skiskiskiski
09:53:18<cads>wonder what I just programmed
09:53:37<dolio>skxy = ky(xy) = y, so skx = i for all x.
09:53:47<ski>i
09:54:16<dolio>Provided the types work out, if you worry about that.
09:55:16<ski>@type let s = ap; k = return; i = id in s k i s k i s k i s k i
09:55:23<lambdabot>forall a. a -> a
10:13:44<Tarrant>So I'm loving this lazy thing. It is kinda freaking me out. So: take 10 (reverse [1..100]) really only generates 100-91?
10:13:59<ejt>nope
10:14:30<Berengal>It generates [1..100] and [100..91]
10:15:12<BONUS>the thing about reverse is that it needs all the elements
10:15:33<Tarrant>That makes sense
10:15:40<idnar>BONUS: surely reverse only forces the spine?
10:15:44<BONUS>haskell is smart but not smart enough to figure out that it could only use 100..91
10:16:07<Tarrant>If you have a pre-generated list can it take the shortcut?
10:16:15<idnar>hmm
10:16:24<idnar>> take 10 (reverse [1..100000])
10:16:30<lambdabot> mueval-core: Prelude.read: no parse
10:16:30<lambdabot> mueval: ExitFailure 1
10:16:44<BONUS>for instance, suppose you have a list iterate (*2) 1
10:17:04<hackagebot>minesweeper 0.4.1
10:17:27<Berengal>> iterate (*2) 1
10:17:32<lambdabot> mueval-core: Prelude.read: no parse
10:17:32<lambdabot> mueval: ExitFailure 1
10:17:40<Berengal>> 2 + 2
10:17:46<lambdabot> mueval-core: Prelude.read: no parse
10:17:46<lambdabot> mueval: ExitFailure 1
10:18:01<Berengal>Lambdabot's in a funk :/
10:18:02<BONUS>> take 3 . reverse . take 10 $ iterate (*2) 1
10:18:06<idnar>@src reverse
10:18:07<lambdabot>reverse = foldl (flip (:)) []
10:18:07<lambdabot> [512,256,128]
10:18:35<BONUS>haskell has to calculate all the elements up to the tenth one
10:19:12<BONUS>it can't figure out that it could just do [2^9, 2^8, 2^7] on its own
10:19:19<Tarrant>Makes sense.
10:19:20<idnar>> take 3 . reverse . take 1000000 $ iterate (*1) 1
10:19:26<lambdabot> mueval-core: Prelude.read: no parse
10:19:26<lambdabot> mueval: ExitFailure 1
10:19:35<idnar>bleh, it takes too long, but I think that should stack overflow
10:19:38<BONUS>this is much like take 10 ( reverse [1..100]), only a bit more obvious
10:19:50<mgsloan>wouldn't it not actually perform the calculations, and thunk them all?
10:20:48<BONUS>fing is, with iterate (*2) 1, to get the nth element, it has to know the n-1th element
10:21:08<BONUS>so they will all have to be evaluated eventually, but most of them will be dropped
10:21:44<opqdonut>yeah, instead of keeping the list in memory, that keeps the huge 2*2*2*2*2*2*...1 thunk in memory
10:24:24<Tarrant>So lets say I have: xs = [1..100]. Using the function: "take 10 (reverse xs)" It reverses 100-91 before realizing that it has the 10 it needs and stops reversing the list, correct?
10:24:48<opqdonut>it has to iterate to the end of the list first
10:24:57<opqdonut>and build the reversed list at the same time
10:24:58<opqdonut>so no
10:25:09<Tarrant>Yes, sorry I'm using [1..100] as shorthand instead of writing [1,2...
10:25:15<opqdonut>but "take 10 [1..1000000]" will only generate ten numbers
10:25:48<opqdonut>Tarrant: getting to the end of a haskell list is O(n)
10:25:55<opqdonut>so no magical help here
10:26:11<Tarrant>opqdonut: Ok I think I have it now.
10:26:16<Beelsebob1>I think the key phraze here is that reverse is strict in the spine of the list
10:26:26<Beelsebob1>so the whole list spine will get evaluated
10:26:31<opqdonut>yeah
10:26:31<Beelsebob1>but not all the numbers will
10:26:35<BONUS>yeah
10:26:40<BONUS>the : : : : [] things
10:26:54<ejt>It's more obvious if you put an expensive comuptation in the list
10:26:56<ejt> take 10 . reverse . map fib $ [1000,999..1]
10:27:05<opqdonut>good point
10:27:09<Beelsebob1>yep
10:27:15<Beelsebob1>so that will only do 10 expensive computations
10:27:38<Beelsebob1>but will still create a 1000 element list of thunks
10:29:46<Tarrant>Thanks. That's really awesome.
10:31:31<BONUS>this is a pretty good read if you want to understand laziness in depth http://en.wikibooks.org/wiki/Haskell/Laziness
10:35:08<koala_man>where does the word "thunk" come from?
10:35:56<quicksilver>old english future tense of 'think'
10:36:07<quicksilver>it means 'something which I may or may not think in the future'
10:37:52<dibblego>@check \a b -> a + b == b + a
10:37:56<lambdabot> mueval-core: Time limit exceeded
10:38:08<ejt>koala_man: http://www.ccil.org/jargon/jargon_35.html
10:38:45<ejt>'the sound made by data hitting the stack' lol
10:41:52<mornfall>Hackage does not love me? : - ( ERROR: dist/hashed-storage-0.3.1.tar.gz: 400 Error in upload
10:51:30<TThijs>can somebody tell me what the $ does in a haskell functions
10:51:55<wjt>TThijs: f <$> x = f x
10:52:01<wjt>erm. f $ x = f x
10:52:32<ejt>TThijs: it applies a function to an argument
10:52:34<wjt>it's used to let you omit parentheses around the argument when they would otherwise be necessary
10:52:39<wjt>> show (5 + 3)
10:52:45<lambdabot> mueval-core: Prelude.read: no parse
10:52:45<lambdabot> mueval: ExitFailure 1
10:52:50<wjt>lambdabot: uh...
10:52:54<wjt>> show (5 + 3 :: Int)
10:52:55<BONUS>f $ x is just f x, thing is it has rly low precedence
10:52:56<lambdabot> "8"
10:53:01<wjt>> show $ 5 + 3
10:53:02<lambdabot> "8"
10:53:07<wjt>> show 5 + 3
10:53:08<lambdabot> No instance for (GHC.Num.Num GHC.Base.String)
10:53:08<lambdabot> arising from the literal `...
10:53:26<BONUS>so instead of writing reverse (take 10 [1..]), you can write reverse $ take 10 [1..]
10:54:00<mgsloan>and usage of $ leads to a very direct path to compositional style
10:54:52<Gracenotes>anything has lower precedence than function application
10:55:29<TThijs>thanks wjt
10:55:43<ejt>try not to chain more than one $ together, use (.) instead. eg, "take 10 $ map fib $ [1..]" is better written "take 10 . map fib $ [1..]"
10:56:51<koala_man>why is it better written like that?
10:57:34<ejt>because it's getting you thinking in a more compositional (point free) way
10:58:22<BONUS>take 10 . reverse . tail $ xs is cool because you can do z = take 10 . reverse and then say z . tail $ xs
10:58:33<BONUS>but you can't say z = take 10 $ reverse
10:58:41<BONUS>cause that tried to apply take 10 to reverse
10:58:42<Gracenotes>not to mention, "a $ b $ c" relies on the infixity of ($) being right.
10:59:04<Gracenotes>so a $ b $ c $ d means (a $ (b $ (c $ d)))
10:59:47<Gracenotes>if the infixity is left -- not a terribly mind-boggling change to make -- then a $ b $ c $ d's won't be valid a . b . c $ d will be, though
11:00:22<Gracenotes>just a note. Since I have heard arguments for changing the infixity before
11:00:47<canvon>so the underlying difference is that (.) is associative, ($) isn't? interesting...
11:00:48<ejt>Gracenotes: wow, that would break _so_ much
11:01:01<ski>Gracenotes : .. except `@',`~',`!',record construction/update)
11:01:41<Gracenotes>then "a $ b $ c $ d" will be equivalent to "a b c d", not "a (b (c d))". It would break a lot, but not if (.) is used where appropriate :)
11:01:50<ski>> (:[]) Node {rootLabel = 1,subForest = []} {rootLabel = 42}
11:01:53<lambdabot> [Node {rootLabel = 42, subForest = []}]
11:02:08<canvon>(okay, ($) can't be associative, as the type signature tells ($) uses two arguments that /have/ to be of different type...)
11:02:36<canvon>Gracenotes: what's the point of using $, then? :)
11:02:54<ski>Gracenotes : additionally, it seems more useful for `$!' to be `infixl' (or renamed)
11:03:07<Gracenotes>canvon: The main difference is how they're used in practice to eliminate parens :)
11:03:27<ejt>canvon: just read some haskell code, it's used a lot
11:03:30<Gracenotes>(.) composes functions. ($) applies functions
11:03:35<canvon>Gracenotes: no, I meant: when it would be changed to being left associative
11:03:39<ejt>plus people pass it around too as ($)
11:03:53<canvon>Gracenotes: in response to what you said
11:03:55<BONUS>it's cool to write stuff like
11:04:19<BONUS>filter (>3) $ take 10 xs
11:04:23<BONUS>you could write that as
11:04:28<BONUS>filter (>3) . take 10 $ xs
11:04:40<BONUS>but i think the first option is better
11:04:58<Gracenotes>canvon: for function application. "map show . filter even $ [1..10]" could still be used. The function is "map show . filter even", and the value is "[1..10]". However, you couldn't chain function application, merely apply more arguments
11:05:40<Gracenotes>so if it was left-associative, you could write "filter $ const True $ [1..10]", although I'm not sure how useful this would be :)
11:06:53<ski>(BONUS : the first option work work with left-associative `$' as well ..)
11:07:05<BONUS>yeah
11:07:08<ski>consider
11:07:10<Gracenotes>plus, ($) and (.) are frequently used together, and mixing left-associative operators and right-associative operators tends to be a nightmare if not done carefully. in languages like C/C++/Java, too
11:07:13<ski> foldl' f z [ ] = z
11:07:14<ski> foldl' f z (a:as) = (foldl' f $! f z a) as
11:07:41<ski>if `$' (and `$!') were left-associative, we could write the last equation as
11:07:48<ski> foldl' f z (a:as) = foldl' f $! f z a $ as
11:08:05<BONUS>yeah, $ should have been made left associative
11:08:24<PeakerWork>ski: that's one big empty list!
11:08:43<quicksilver>there is an argument not to make it associative
11:08:48<ski>ACTION likes the empty lists lining up with the cons pattern :)
11:09:00<quicksilver>withWidgets $ withFudgets $ do .....
11:09:00<BONUS>i never thought of matching up the [ and ] and the cons pattern
11:09:04<BONUS>it actually looks really nice
11:09:25<quicksilver>sorry "not to make it associate to the left", I mean
11:09:58<ski>you could use `.' there .. but one might consider that unnatural, i suppose
11:10:01<Gracenotes>BONUS: hm. I like the idea of matching "(x:xs)" with "[] " (with spaces), mahself
11:10:22<ski>(i don't recall which i've used)
11:10:41<quicksilver>ski: that's not quite the point
11:10:51<quicksilver>ski: it was a warmup
11:10:54<quicksilver>ski: now suppose you have
11:11:14<quicksilver>withThisWidget $ \widg -> withThisFudget $ \fudg -> do ....
11:11:22<quicksilver>ski: now you *really* have to use $.
11:11:49<quicksilver>ski: so the full argument is - it would be annoying swapping between $ and . based on whether the with construct has a binding or not
11:12:11<Saizan>nah, you simply rewrite that in the ContT monad ;)
11:12:11<ski>Gracenotes : how about lining up ` Nothing ' with `(Just foo)' ? :)
11:12:31<ski>(Gracenotes : or `(Left e)' with `(Right a)' ?)
11:12:58<Gracenotes>I'd probably go with "(Left e) " and "(Right a)" :) But it depends
11:12:59<ski>quicksilver : i see your point
11:13:10<quicksilver>I line up the = signs in defintions. I don't bother to line up the () in the constructors.
11:13:22<quicksilver>if there are multi-arg constructors I line the args up though
11:13:34<quicksilver>(or multiple args to the function)
11:13:52<Gracenotes>it depends..
11:13:52<quicksilver>ski: it was someone else's point, I dont' remember whose, but it struck me as a good one :)
11:13:56<Gracenotes>hm
11:15:18<Gracenotes>on the other hand, changing the infixity of (.) from right wouldn't exactly break anything
11:15:46<Gracenotes>but.. given the way we think of composition.. possibly not bright
11:15:54<ski>it might be nice if editing modes lined up things like the `='/`->' (& `|') ..
11:16:19<Twey>ski: I always line up my arguments
11:16:33<philipp_>i've got a function with a memory leak because of lazyness, printing the variable seems to fix this but how can i get the same effect without printing? already tried several possibilities with `seq` but it seems that i need hnf data, here's the function: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5497#a5497 where " lift $ print (f2i 0)
11:16:38<philipp_>is the fix
11:16:50<Twey>You end up with a sort of ‘table’ of functions, instead of a bunch of discordant lines
11:16:56<ski>Twey : maybe you should create a poll for this ? :)
11:17:08<ski>s/you/we/
11:17:19<Twey>It's possibly the only good thing about different patterns require the same number of arguments :-P
11:17:23<Twey>A poll? What sort of a poll?
11:17:29<ski>@list poll
11:17:30<lambdabot>poll provides: poll-list poll-show poll-add choice-add vote poll-result poll-close poll-remove
11:17:35<Twey>Oho
11:17:36<Twey>Good idea
11:17:42<Twey>How does this work?
11:17:53<ski>@help poll-add
11:17:54<lambdabot>poll-add <name> Adds a new poll, with no candidates
11:18:02<ski>@help choice-add
11:18:03<lambdabot>choice-add <poll> <choice> Adds a new choice to the given poll
11:18:03<Twey>@help choice-add
11:18:04<lambdabot>choice-add <poll> <choice> Adds a new choice to the given poll
11:18:05<Twey>Heh
11:18:11<Twey>Noted
11:18:28<quicksilver>ski: I make frequent use of M-x align-regexp
11:18:31<Twey>@poll-list
11:18:32<lambdabot>["logoVotingMethod"]
11:18:41<Twey>@poll-show logoVotingMethod
11:18:41<lambdabot>["Schulze"]
11:18:46<Twey>o.@
11:19:20<Saizan>philipp_: can you paste the definition of Model too?
11:19:21<Twey>@poll-add functionFormatting
11:19:22<lambdabot>Added new poll: "functionFormatting"
11:19:31<ski>ACTION hasn't seen that emacs command before ..
11:19:40<philipp_>Saizan: sure, one second
11:19:54<Twey>@choice-add functionFormatting Line up = and all arguments
11:19:54<lambdabot>usage: @choice-add <poll> <choice>
11:20:09<Twey>ACTION scratches his head.
11:20:33<philipp_>Saizan: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5499#a5499
11:22:05<quicksilver>ski: it's great for not just making code pretty. It also lets you line up text data into columns, so you can edit them with rectangle mode
11:22:08<Saizan>philipp_: i'd probably make all the fields strict
11:22:19<Twey>quicksilver: Cool
11:22:38<Saizan>philipp_: also, i don't see where the getF2I field is populated
11:22:46<philipp_>Saizan: how? bang patterns?
11:23:16<Saizan>philipp_: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5499#a5500
11:23:24<mornfall>Oh.
11:23:29<ski>(quicksilver : ty)
11:23:36<mornfall>Btw, what's the cabal version that comes with ghc 6.8?
11:23:41<philipp_>Saizan: thanks, I'll try that
11:23:49<dcoutts>mornfall: 1.2.x
11:25:19<hackagebot>hashed-storage 0.3.1
11:25:22<mornfall>Hm, "cabal upload" should probably give full error text from hackage, not just "ERROR". :)
11:25:26<philipp_>Saizan: now i get a strange error while running the binary
11:25:33<ski>philipp_ : style comment : i'd define arnold' in a `let' in the `do'-block, to avoid passing in `fina',`finb',`f2i' .. or even use `flip parMapM [(a,b) | ...] $ \(a,b) -> do ...'
11:25:55<Saizan>philipp_: which error?
11:26:05<philipp_>Saizan: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5499#a5501
11:26:11<philipp_>ski: thanks
11:27:09<dcoutts>mornfall: http://hackage.haskell.org/trac/hackage/ticket/549
11:27:14<Saizan>philipp_: uhm, that's weird, try with -fforce-recomp
11:27:30<ski>i.e.
11:27:34<ski> flip parMapM (liftM2 (,) omegaA omegaB) $ \(a,b) -> do
11:27:36<ski> ...
11:27:38<mornfall>dcoutts: : - )
11:27:58<dcoutts>mornfall: patches gratefully accepted :-)
11:28:01<philipp_>Saizan: didn't work
11:28:05<mornfall>I imagine. :)
11:28:24<mornfall>But if I get cabal hacking time, I'll first and foremost fix the double compile that darcs suffers.
11:28:28<Saizan>philipp_: i meant recompiling with that flag
11:28:42<Saizan>philipp_: if it still doesn't work it looks like a ghc bug
11:28:49<philipp_>I did
11:28:54<dcoutts>mornfall: great then you can work on this ticket, because the double compile is fixed :-)
11:28:55<mornfall>Which ought to have happened long time ago, but I somehow managed to not have that time.
11:29:04<mornfall>dcoutts: \o/
11:29:05<mornfall>: - )
11:29:20<mornfall>Maybe I should upgrade my cabal, then. :)
11:29:41<dcoutts>mornfall: it's not released yet, it went in the day before yesterday
11:29:57<mornfall>Well, I can sustain some breakage from unreleased cabal versions.
11:29:59<philipp_>Saizan: it's probably also not a good idea to use bang patters since constructing the Model takes a lot of time and the program should only construct those Models which are actually used in a function
11:30:01<mornfall>I guess.
11:30:10<mornfall>: - )
11:30:21<dcoutts>mornfall: then you need Cabal head and cabal-install head
11:30:30<mornfall>Aye, working on it. Let's see.
11:30:54<Saizan>philipp_: the strict fields will only ensure that if you use a Model it won't hide unevaluated thunks in it
11:31:07<Saizan>philipp_: they won't force the creation of the whole model by themselves
11:31:26<philipp_>Saizan: ah ok
11:31:32<philipp_>that should be fine
11:31:50<Saizan>philipp_: however since most fields are functions they can "hide" unevaluated thunks inside them, depending on how they are constructed
11:33:36<Saizan>or keep something alive that should be GC'ed
11:33:55<Saizan>you could use heap profiling to get a better idea of what's going on
11:34:03<Saizan>?google ghc heap profiling
11:34:05<lambdabot>http://www.haskell.org/ghc/docs/latest/html/users_guide/prof-heap.html
11:34:05<lambdabot>Title: 5.4.�Profiling memory usage
11:34:18<philipp_>Saizan: thanks!
11:35:35<philipp_>Saizan: now it works, but it doesn't have the same effect as printing
11:37:03<Saizan>philipp_: you mean it uses less memory but not so much less?
11:37:28<Saizan>maybe with "!f2i <- gets .."
11:37:53<Saizan>the code is a bit dense and partial so i'm kind of shooting in the dark :)
11:38:24<philipp_>also doesn't work, memory goes up all the time
11:39:42<philipp_>Saizan: added some revisions
11:39:55<Saizan>a bruteforce option is to write !() <- rnf (f2i 0) `seq` return ()
11:40:11<Saizan>instead of the lift (print (f2i 0))
11:41:40<philipp_>yes, that works
11:41:56<LeCamarade>@tell conal Well, it was only tangentially about threads. I had asked about what prompted different behaviour between native and runhaskell, and you asked if my program was threaded.
11:41:57<lambdabot>Consider it noted.
11:43:00<LeCamarade>@tell conal Well, it is threaded, and learning the vagaries of threads under both native and runhaskell GHC programs (from you, I hoped) would likely be helpful.
11:43:00<lambdabot>Consider it noted.
11:44:35<philipp_>(f2i 0) `seq` parMapM ... also seems to work
11:44:59<Saizan>LeCamarade: native without -threaded doesn't use the threaded runtime which is instead used by ghci and runghc
11:45:08<MarcWeber>Any chance implementing something like SQLAlchemy (python lib) in haskell ?
11:45:30<Saizan>LeCamarade: the threaded runtime can run haskell threads in multiple OS threads
11:45:31<Baughn>MarcWeber: What's it do?
11:46:03<Baughn>LeCamarade: The threaded runtime can also spawn OS threads to handle blocking system/library calls, which may otherwise block a program with multiple haskell threads
11:46:12<LeCamarade>Ha!
11:46:18<MarcWeber>Baughn I'ts a SQL framework for python including an ORM (object relational mapper). So you can get "users" and lazy load associated adresses.
11:46:32<quicksilver>I started to explain this to LeCamarade yesterday
11:46:37<LeCamarade>So ... I'm probably being bitten by that.
11:46:40<quicksilver>evidently my explanation didn't entirely satisfy :)
11:46:41<Baughn>MarcWeber: Well, an object-relational mapper doesn't really make sense in haskell?
11:46:53<LeCamarade>quicksilver, You were much help, but I want a PhD in Haskell threads, it seems. :o)
11:47:02<Baughn>MarcWeber: Lazily reading results, of course, is easy.
11:47:04<quicksilver>MarcWeber: lazy loading of columns is the biggest make an ORM ever made :)
11:47:06<MarcWeber>Baughn It depends on how you do define "object" if you consider AGDTs beeing objects (estimatino) then yes!
11:47:08<LeCamarade>GHC threads, to be precise.
11:47:24<quicksilver>LeCamarade: did you try compiling with -threaded?
11:47:43<MarcWeber>quicksilver The point is : It's short to write. I don't even know if you can get such a nice syntax in haskell.
11:48:10<LeCamarade>quicksilver, Yes, and I'm closer to a solution because of that.
11:48:11<quicksilver>I was making a specific point about lazy column loading.
11:48:17<LeCamarade>Now, it blocks immediately.
11:48:19<quicksilver>not a general point about conveneitn database mappers.
11:48:28<MarcWeber>And if it works (I haven't tried) its really nice to use. While writing you applications you don't want to bother with IO, you don't want to think about monads, you don't want to think about relations. This lib seems ome close to this.
11:48:28<LeCamarade>It deadlocks immediately, rather.
11:49:01<Baughn>MarcWeber: You can do quite interesting things with SYB/TH and relatives
11:49:02<quicksilver>I think some of the haskell database libraries try to be convenient in this way
11:49:08<quicksilver>I haven't used any opf them.
11:49:25<MarcWeber>Baughn You can't do users[0].adresses[0].user.name
11:49:30<Baughn>MarcWeber: Also, in my experience, you /do/ want to think about monads. They help a lot, when appliable.
11:49:47<Baughn>MarcWeber: Sure you can. You might have to write the code first, but you can do that.
11:50:24<MarcWeber>Baughn How does it look then?
11:50:35<p_l>MarcWeber: I think I had seen it work quite nicely, easily, in something that might be quite nicely modified into functional world...
11:50:52<quicksilver>users ! 0 # Address ! 0 # User # Name
11:51:02<quicksilver>assuming appropriate definitions (and fixities!) for ! and #
11:51:17<MarcWeber>users >>= \l -> l!!0 >>= adresses >>= x \-> x!!1 >>= user ? @ Baughn
11:51:28<Baughn>MarcWeber: Ugh. That's awful.
11:51:35<quicksilver>where Address, User, Name would be constructors from appropriate field datatypes.
11:52:43<MarcWeber>Baughn By the way my example showed how back references can be used.
11:53:11<Baughn>MarcWeber: Unfortunately it was also unreadable. I prefer mercury's version.
11:53:20<MarcWeber>users[0].adresses[0].user.name thus the user at the end is the same object as users[0]. Of course you can start messing around with fix types and such.. but you don't want to.
11:54:01<MarcWeber>So how I can I represent this 1 user has many addresses relation easily? Using data User = User [Adress] ?
11:54:20<Baughn>That's one way
11:54:36<Baughn>Of course, instead of Address being the literal address value, it'd probably be some kind of reference to SQL-reading code
11:54:39<MarcWeber>Then when passing an address I don't have a reference to users. (I know this is nice if you want to start using multithreading..)
11:55:44<MarcWeber>Baughn: users[0].adresses[0].user.name so how many selects do you want to run here?
11:56:05<Baughn>MarcWeber: One, of course
11:56:52<Baughn>Though it'd be a pretty complex one, I suppose
11:57:10<Baughn>Still. There's only one deRefSQL call in there.
11:57:31<ketil>Is there a way to get my own URL using (Fast)CGI?
11:57:31<lambdabot>ketil: You have 3 new messages. '/msg lambdabot @messages' to read them.
11:57:49<MarcWeber>Baughn: The alchemy lib can do more. You can just do users[3].name="newname" and do a session.commit() afterwards. Only the "users" which have changed will be written back to the database.
11:58:15<Baughn>MarcWeber: A simple matter of programming. What's your point?
11:58:53<MarcWeber>Baughn That I'd like haskell to take off. But all the sql libs made me having headache for different reasons.
11:59:22<quicksilver>well it's certainly not a limitation of haskell as a language
11:59:23<MarcWeber>And reading that documentation made me think: Yes, that's what I want to use, no matter wether it has been written in haskell or python.
11:59:32<quicksilver>it may be a limitation of the libraries, or their docs
12:12:42<saynte>WTB: someone who has used the LLVM hackage-package ;)
12:13:52<ejt>I played with LLVM last week
12:14:06<ejt>working through Lennarts posts
12:15:25<portartus>Hallo
12:15:57<portartus>ihr seid doch alle schwul!
12:16:29<portartus>hello
12:16:33<portartus>any1 here?
12:17:35<Beelsebob>people are here
12:17:41<Beelsebob>but you may want to try #haskell.de
12:17:48<ejt>he's gone
12:17:52<MarcWeber>he's gone and he's lacking brain.
12:17:52<Beelsebob>oh, so he has >.<
12:18:26<MarcWeber>Beelsebob: he said "you're all gay"
12:18:42<quicksilver>statistically it's likely that some of us are
12:18:48<quicksilver>but overwhelmingly unlikely that we all are
12:18:58<quicksilver>poor chap just doesn't understand demographics very well
12:19:24<saynte>ejt: have you tried to create anything like a compiler yet?
12:19:40<saynte>ejt: in the sense of going from AST -> bytecode using the bindings?
12:19:51<ejt>saynte: no, I was tempted to code up the 'kaleidescope' example from the llvm docs
12:20:36<ejt>I basically worked through Lennarts posting, then decided that I need to understand LLVM more so worked through writing assembly directly for a bit
12:21:15<ejt>I'm looking at it to compile a little fractal rendering DSL
12:21:19<saynte>ejt: hmm. yeah. i was curious, because it seems like the strong typing that they have used to represent functions is rather too restrictive.
12:21:39<ejt>I had terrible trouble with the for loop construct
12:22:02<ejt>and it's return type
12:22:18<saynte>In their "examples" directory, or from the LLVM tutorial?
12:22:22<tux-foo>twanvl, ping
12:22:36<tux-foo>twanvl, tux-foo=foo-nix
12:22:41<ejt>from Lennarts posting
12:22:42<jacobian>yarg, for some reason my program isn't lazy enough
12:23:03<ejt>there is an examples dir of haskell code ?
12:25:14<saynte>yeah, in the repository/package.
12:25:20<saynte>did you get it from cabal?
12:26:33<ejt>y, but I just installed it
12:26:43<ejt>ok, I should look through those
12:27:15<ejt>I was very impressed with the code that LLVM produces
12:27:46<saynte>yeah, it has this reputation :)
12:27:51<ejt>very similar performance to gcc on the little examples I tried
12:28:13<ejt>what are you using it for ?
12:28:42<saynte>and the binding the have on hackage is pretty good i think except for this one area that I can't for the LIFE of me figure out how to write functions from an AST in it.
12:28:54<saynte>just trying to write a small language as an experiment.
12:29:02<saynte>so far (as you can tell) I am hung up on functions.
12:31:00<ejt>ok, let me dig a bit ...
12:31:55<saynte>yeah. the trick is this: it's easy to do if you write your functions in Haskell, because you'll define them like a Haskell function, and it will use it's type-class trickery to make it all ok.
12:32:30<saynte>however, if you have a representation of a function from a file at runtime, then you're in more trouble.
12:32:40<ejt>hmm, I don't think that's much different
12:32:43<ejt>let me try
12:33:13<blackh>Hi all. Is there a 'touch' function that allows you to prevent a data structure (with a finalizer attached) getting GC'ed, like touchForeignPtr but for general data structures?
12:33:34<ejt>blackh: just hold onto a reference ?
12:33:52<Lemmih>blackh: The short answer is no.
12:34:20<blackh>ejt: I've pulled a Chan out of my data structure and I'm waiting on that, and I want to keep it alive until something is received... I could add the finalizer to the Chan but that doesn't solve the problem.....
12:34:36<blackh>because Chan in turn has its own internal structure.
12:34:45<saynte>ejt: a good example may be to try to create an "incr" function, fairly simple but should show you the problem.
12:34:48<blackh>Lemmih: Thanks. I'll see if I can't dream something up.
12:34:52<ejt>saynte: y
12:35:13<ejt>blackh: just have another thread wait on the channel ?
12:36:16<blackh>ejt: Well, waiting on the Chan doesn't actually necessarily keep the top-level 'Chan' data structure alive. That assumes things about how it's implemented.
12:36:32<saynte>ejt: because it's very hard to do. so essentially go from a function data-type to an LLVM function.
12:37:25<blackh>In case anyone's wondering what I'm trying to do, it's a client for a communications channel (socket based). I want the socket to get cleaned up when the client is no longer used.
12:37:52<blackh>I just want to ensure it gets kept alive for the during the 'request' function.
12:38:46<blackh>Not very functional code. :)
12:42:26<blackh>touch x = newIORef x >> return () <-- this seems to work
12:44:12<Lemmih>blackh: That's unlikely to work with compilers such as LHC.
12:47:30<blackh>Lemmih: Thanks. Well, either I could use something from FFI (since C must makes concrete assumptions), or I maybe I re-think the whole thing.
12:48:02<byorgey> /win 3
12:48:09<byorgey>sigh
12:48:55<Lemmih> /fail (:
12:49:00<ejt>saynte: have you looked at the BASIC example ?
12:49:48<ejt>(and I see your problem :( )
12:52:56<saynte>ejt: just took a look, that's kinda ninja, hehe.
12:53:45<saynte>ejt: yeah, it's sort of fundamental i think. i've considered using existential types, TH and Data.Dynamic, i don't think any of those give a solution.
12:54:55<saynte>I think it just needs a less-typed version of the function to do it. In a compiler you're probably doing your own type-checking anyway, so I think this is ok. Although I'd be curious to see if there is a way to do it with the available bindings.
12:55:36<ejt>augustss: ?
13:00:21<RayNbow>Functor has fmap :: (a->b) -> f a -> f b, ContraFunctor has contramap :: (b->a) -> f a -> f b... is there a class that contains a function of type (a->b) -> (b->a) -> f a -> f b?
13:01:11<Saizan>ExpFunctor in category-extras
13:02:43<RayNbow>Saizan: ah nice... and there's also a link to the Comonad Reader :)
13:02:46<RayNbow>thx :)
13:03:08<RayNbow>(not that I'm all too familiar with CT, but I was wondering about it earlier today when I was waiting for a train to depart)
13:11:32<RayNbow>Saizan: data Socket a = Socket (Source a) (Sink a) -- this would be a nice candidate for ExpFunctor, right? :)
13:12:35<ejt>saynte: maybe the point is the type of your entry point should always be the same
13:12:42<Saizan>probably, iirc the definition of Source and Sink
13:14:14<kig>how do i make a ptr out of a bytestring? (drudging through using cairo imagesurfaces as gl textures)
13:14:48<Saizan>look at Data.ByteString.Internal
13:15:16<saynte>ejt: could be, but this is rather restrictive. I feel that it's just a design flaw.
13:15:35<RayNbow>Saizan: well, I don't know whether Source/Sink already exists in some package... but they seem like a functor/contrafunctor resp. to me
13:16:35<MyCatVerbs>blackh: er, if you want Haskell values to stay in-place and existent for specific lengths of time, use Foreign.StablePtr
13:17:07<blackh>MyCatVerbs: Thanks - that looks promising.
13:17:38<Saizan>RayNbow: ah, i thought you were referring to reactive
13:20:06<kig>Saizan: thanks, let (fptr,_,_) = toForeignPtr bstr in let ptr = unsafeForeignPtrToPtr fptr seems to work
13:20:47<kig>now to bang head against getWidth and getHeight being inside Render monad
13:21:30<quicksilver>kig: you don't need to nest the lets like that
13:21:53<quicksilver>let (fptr,_,_) = toForeignPtr bstr; ptr = unsafeForeignPtrToPtr fptr in ...
13:22:52<quicksilver>and 'withForeignPtr' is the preferred way, not unsafeForeignPtrToPtr
13:23:29<kig>oh, there's withForeignPtr. nice, thanks
13:23:40<quicksilver>and finally...
13:23:52<quicksilver>ignoring the two other fields of toForeignPtr is not a good idea.
13:23:57<quicksilver>they are there for a reason :P
13:28:31<blackh>Lemmih, ejt, MyCatVerbs: The whole finalizer thing doesn't work. GHC seems to be optimizing out the containing object. I need to abandon the idea and close it explicitly with a 'withClient' sort of function. Thanks again.
13:37:46<quicksilver>blackh: if you need reliable finalizers, attach them to an MVar or an IORef
13:37:46<lambdabot>quicksilver: You have 1 new message. '/msg lambdabot @messages' to read it.
13:38:02<quicksilver>lambdabot: why tell me that now? I only said something 14 minutes ago?
13:38:05<quicksilver>@messages
13:38:05<lambdabot>ivanm said 3d 41m 19s ago: after playing with kuribas' indentation mode, I recall using it once and discarding it because I keep expecting tab to indent no matter where in the line I am (and
13:38:05<lambdabot>backspace doesn't unindent the same amount as tab indents either) :s
13:38:07<ksf>@seen conal
13:38:07<lambdabot>I saw conal leaving #haskell and #ghc 4m 14d 8h 23m 51s ago, and .
13:38:11<quicksilver>Oh, that's an old one.
13:38:21<blackh>quicksilver: much appreciated
13:38:37<ksf>someone raise lambdabot's wage, she can't even afford her meds.
13:39:16<ejt>has conal really been missing for 4 months !
13:40:28<Gracenotes>is there a particular reason Real requires Ord?
13:40:41<byorgey>ejt: no =)
13:40:58<byorgey>looks like lambdabot crashed and lost some state.
13:41:22<Gracenotes>seen has been somewhat suspect..
13:41:27<Gracenotes>preflex: seen conal
13:41:27<preflex> conal was last seen on #haskell 16 hours, 32 minutes and 34 seconds ago, saying: mempty :: Sum a
13:50:06<quicksilver>blackh: using addMVarFinalizer, not using the standard addFinalizer
13:50:14<quicksilver>the standard addFinalizer is soggy and hard to light.
13:53:56<kig>if i hit a mysterious problem like image w*h*4 != dataLength, i should throw an exception, right? or wrap the retval inside Maybe ?
13:54:36<ksf>loadFile :: Either LoadError Image
14:00:55<mux>someone unbreak reddit please!
14:21:00<hackagebot>bindings-common 0.1.2
14:26:01<hackagebot>bindings-libusb 0.0.2
14:28:29<PeakerWork>given an incoming XML on top of streaming data -- what XML library lets me read it incrementally and tell me when its done?
14:29:50<quicksilver>none of them, probably.
14:30:36<PeakerWork>so I have no way to read a "whole XML" from a pipe?
14:31:30<quicksilver>dunno for sure
14:31:33<mux>HaXml can do that with lazy parsing
14:31:33<quicksilver>I only said 'probably'
14:31:54<mux>it's actually the only XML library for haskell that I've used that allowed me to parse a _big_ XML file incrementally
14:31:55<quicksilver>mux: HaXml knows when it is done and gives you back the rest of the stream then?
14:32:07<mux>no, but the lazy parser of HaXml lets you parse only part of the document
14:32:15<mux>you'll have to write some boilerplate code around that
14:34:02<bd_>mux: clear your reddit cookies and you should be able to get in, apparently
14:34:27<bd_>though commenting seems broken still
14:34:59<mux>bd_: mmm, just tried that and I still get a "service unavailable" error
14:35:16<quicksilver>mux: well, you can't get a stream back out of a String which has interleaved IO in it
14:35:25<quicksilver>that's one of the many many reasons that interleaved IO is broken.
14:36:17<mux>quicksilver: yeah, I was thinking about a usage scheme when you read incrementally, ie with hGetLine
14:37:10<quicksilver>haxml supports that?
14:37:14<quicksilver>you can feed it lines one by one?
14:37:36<mux>yes
14:37:45<mux>this is how I achieved parsing a ~50MB XML file
14:37:51<mux>any other way would result in a space leak
14:38:13<quicksilver>mux: Nice.
14:38:14<quicksilver>haxml++
14:38:25<quicksilver>PeakerWork: The correct answer is: Yes, HaXML
14:38:34<quicksilver>although you need to development version for the incremental parsing.
14:38:37<quicksilver>IIRC>
14:38:42<mux>but in my case I didn't have to hGetLine stuff; I just used readFile
14:39:12<mux>but it worked, otherwise my program would have quickly crashed after having consumed all of my RAM
14:39:51<blackh>Hexpat does lazy parsing too
14:40:15<mux>but it's impure :-)
14:40:27<blackh>No it isn't - I wrote it, so I should know
14:40:50<mux>I was assuming Hexpat would be a bidnings module to expat
14:40:59<blackh>It is, but I did it all properly
14:41:33<quicksilver>mux: readFile is the impure thing, if anything is impure :P
14:41:38<mux>blackh: however you did it, it's still in IO, right?
14:41:43<mux>quicksilver: hah. touché.
14:42:05<blackh>mux: There's a low-level interface that's in IO and a high-level interface that's pure
14:43:09<mux>cool
14:46:37<mux>blackh: mmm, except that it doesn't look like hexpact can actually do incremental XML parsing (not lazy XML parsing), at least not without using the SAX interface$
14:47:12<blackh>mux: It can definitely do lazy parsing with the tree interface.
14:47:26<blackh>I've written a lot of code that relies on that.
14:47:43<mux>blackh: I repeat that I'm talking about incremental parsing, not lazy parsing
14:48:04<blackh>mux: Oh. What's incremental parsing?
14:48:10<mux>ie, a way to explicitely parse an incomplete XML document
14:48:12<rick_2047>can haskell have function overloading???
14:48:39<mux>(like you get when you parse XML streams such as the Jabber protocol - it seems this was the motivating example for this technique in HaXml)
14:49:33<blackh>mux: I use hexpat to implement communications protocols using lazy parsing.
14:49:51<quicksilver>rick_2047: yes. That's what typeclasses are for.
14:50:12<rick_2047>quicksilver, typeclasses ok
14:50:26<blackh>mux: But you're right - you can't do it explicitly, i.e non-lazily, without using the lower level interface.
14:50:53<uccus>hi guys, anyone here uses Cygwin? I am trying to build hmatrix and running into trouble, experienced help needed
14:51:11<mux>blackh: this is way cool then; what I liked about the HaXml way was that I was __sure__ that it didn't try to read more of the file than it should :-)
14:51:34<mux>ACTION notes most reddits are back up except proggit
14:51:56<quicksilver>ACTION dislikes this use of the term "lazy"
14:52:05<gnuvince>mux: nothing works here :(
14:52:16<quicksilver>I think it inhibits discussion.
14:52:38<mux>gnuvince: it's a bit weird though: I can access haskell reddit for instance, but only the main page. clicking on "new" gives me a service unavailable error
14:52:47<borisl>> map (+1) [1..10]
14:52:50<lambdabot> [2,3,4,5,6,7,8,9,10,11]
14:53:34<gnuvince>That'll teach those guys not to have XXL hoodies!
14:54:40<blackh>mux: It could well be that it is technically incorrect to rely on Haskell being maximally lazy. I will add incremental parsing next time I work on hexpat.
14:55:07<mux>blackh: it's true that the "level" of laziness (cannot think of a better term) isn't guaranteed by the standard, AFAIK
14:55:14<blackh>mux: Thanks for the assistance you inadvertently gave me.
14:55:26<mux>blackh: I'm glad :-)
14:56:01<blackh>mux: I've had a few people say they wanted features that I hadn't thought of, so it's great to talk to people about it.
14:57:23<PeakerWork>ByteString.Char8 returns its own bytestring type -- how can I use existing functions that work with either Strict or Lazy bytestring with it? e.g: Data.Binary.Get.runGet?
14:59:03<alexsuraci>Is HaskellDB the preferred way to work with databases?
14:59:08<quicksilver>alexsuraci: no.
14:59:22<alexsuraci>It hasn't been updated in a while and the documentation on it seems pretty sparse
14:59:27<quicksilver>alexsuraci: AFAIK there is no preferred way.
14:59:38<quicksilver>there are just a bunch of libraries, each one used by a small number of people.
14:59:46<quicksilver>takusen, HDBC, haskelldb
14:59:57<alexsuraci>Haven't heard of takusen, I'll check that out
15:00:00<Saizan>PeakerWork: it returns either a strict or a lazy BS, depending which .Char8 it is
15:00:10<Saizan>PeakerWork: there are only two ByteString types
15:00:17<PeakerWork>Saizan: ah, thanks
15:01:02<alexsuraci>Huh, no MySQL support on that one, strange
15:01:06<blackh>BerkeleyDBXML
15:01:22<alexsuraci>well, "full" support anyway
15:07:18<quicksilver>alexsuraci: that's because mysql is so full of fail no self-respecting haskell programmer would use it? ;)
15:08:11<alexsuraci>I understand that, but it's the most popular with whoever will be using this software.
15:08:37<Saizan>hsql has mysql support, iirc
15:09:03<alexsuraci>Saizan: yea, it does
15:17:15<gwern>it always distresses me to see how shite my computer performs when a little load is put on the hard drive
15:17:39<gwern>I knew when I was building it that hard drive performance was more important these days than ram or gigahertz, but apparently I didn't compensate enough
15:18:15<walter_>Did anyone know something about HStringTemplate? I want to put serveral into <p>$paragraph$</p>, but I dont know exactly how many paragraph, it depends on the data I get.
15:22:33<doserj>walter_: I think there is sth like $foreach x in list$ sth $end$?
15:23:25<walter_>doserj, yeah, that is what I need.
15:26:08<walter_>doserj, thanks. $foreach works well.
15:31:53<skorpan>i'm looking for a function which given a function f and an integer n returns the composition of "n" fs
15:32:09<skorpan>i.e. g f 3 = f . f . f
15:32:13<skorpan>is this possible?
15:32:19<Beelsebob>@hoogle (a -> a) -> Int -> a -> a
15:32:20<lambdabot>Data.Sequence adjust :: (a -> a) -> Int -> Seq a -> Seq a
15:32:20<lambdabot>Data.IntMap adjust :: (a -> a) -> Key -> IntMap a -> IntMap a
15:32:20<lambdabot>Data.Generics.Basics gmapQi :: Data a => Int -> (a -> u) -> a -> u
15:32:28<Beelsebob>nope, none of them...
15:32:29<skorpan>already hoogled :)
15:32:55<mux>skorpan: I don't know how to write it point-free but you can write it point-wise with iterate and (!!)
15:32:57<Beelsebob>> let nTimes f 0 = id; nTimes f n = f . nTimes f (n-1) in nTimes (+1) 6 $ 1
15:32:59<lambdabot> 7
15:33:19<trez>är la bara att skriva själv
15:33:19<mux>> let double = (*2) in iterate double 1 !! 10
15:33:20<lambdabot> 1024
15:33:26<skorpan>trez: redan gjort, men vill ha en snyggare
15:33:31<mux>> let double = (*2) in iterate double 1 !! 11
15:33:32<lambdabot> 2048
15:33:37<Beelsebob>> let nTimes f = foldr (f .) id . enumFromTo 1 in nTimes (+1) 6 $ 1
15:33:39<lambdabot> No instance for (GHC.Num.Num (a -> a))
15:33:39<lambdabot> arising from the literal `1' at <...
15:33:45<skorpan>:t iterate (*2)
15:33:46<lambdabot>forall a. (Num a) => a -> [a]
15:33:49<Beelsebob>oops, not quite right
15:37:29<Philonous>@type replicate
15:37:31<lambdabot>forall a. Int -> a -> [a]
15:38:17<skorpan>> (replicate 3 (*2)) 1
15:38:18<lambdabot> Couldn't match expected type `t1 -> t'
15:38:30<skorpan>:t replicate 3 (*2)
15:38:31<lambdabot>forall a. (Num a) => [a -> a]
15:39:04<ski>it might be nice with a `Num Church' where `newtype Church = MkChurch {unChurch :: forall a. (a -> a) -> (a -> a)}
15:39:05<skorpan>> foldr1 (replicate (*2)) 1
15:39:06<lambdabot> The section `GHC.Num.* 2' takes one argument,
15:39:06<lambdabot> but its type `GHC.Types.Int'...
15:39:18<Beelsebob>> let nTimes f n = foldr (.) id $ replicate n f in nTimes (+1) 6 $ 1
15:39:19<lambdabot> 7
15:40:36<PeakerWork>Why doesn't Get have a typeclass MonadGet/etc like State/et-al?
15:41:05<PeakerWork>I would like getWord8 to be in MaybeT Get Word8 rather than in Get Word8 so it can fail reasonably
15:43:03<quicksilver>PeakerWork: i suspect the answer is because the authors were terribly concerned with extremely good performance
15:43:11<quicksilver>(to both of your questions, basically)
15:43:28<PeakerWork>but type-classes can be inlined in compile-time when possible :-(
15:43:29<quicksilver>I think it's axiomatic that Get Word8 can't fail; failure should be handled at a higher level.
15:43:46<Beelsebob>can't it?
15:43:53<PeakerWork>quicksilver: Well, getByteString can fail, and it fails with pure exceptions, rather than the polymorphic method "fail"
15:43:55<Beelsebob>what if it's past the end of the input?
15:44:09<PeakerWork>quicksilver: (it does use "fail" but its hard-coded to be in the Get monad, rather than some monad that had MonadGet)
15:44:24<quicksilver>by 'axiomatic' I mean 'an assumption of the design'
15:44:48<quicksilver>you call runGet on ByteStrings - you're only supposed to call it on ByteStrings which hold enough input
15:44:52<PeakerWork>quicksilver: I need to manually call "remaining" and verify its big enough, which forces the rest of the string :(
15:44:57<quicksilver>to do otherwise is a programming error, in terms of the API.
15:45:06<PeakerWork>quicksilver: what if I want binary parsers that can fail?
15:45:10<PeakerWork>Get is no good?
15:45:37<quicksilver>get isn't really a parser in the normal sense
15:45:43<quicksilver>it's a high performance bytestring reader
15:45:55<quicksilver>it's pretty limited as a parser
15:45:57<PeakerWork>its not a terribly powerful parser, but it is a kind of parser combinator
15:46:04<quicksilver>but you can layer a parser above it.
15:46:24<PeakerWork>are you supposed to really verify that the data you're giving to Get wasn't corrupted/truncated along the way?
15:46:46<quicksilver>look I'm not saying it's perfect, or it can do everything.
15:46:52<quicksilver>I'm explaining its intended use.
15:47:04<quicksilver>I"m not saying it wouldn't be better if it was different, or you can't imagine something better, or...
15:47:34<quicksilver>of course, no reliable system should even consider using Get on a Lazy Bytestring which comes from IO
15:48:10<quicksilver>reliability and interleaved IO are at worst completely incompatible, and at best a research topic.
15:49:03<Saizan>and in teh middle you can use attoparsec
15:49:32<quicksilver>attoparsec is described as 'text-oriented'
15:54:39<fracture>how do you wait for input from multiple Handles in haskell? (i.e. something like unix select)
15:55:11<mux>fracture: you typically don't do that but use threads instead
15:55:18<Beelsebob>fracture: there may be a more basic way of doing it, but fire off threads to monitor each
15:55:24<Beelsebob>and get each to feed into a channel when it gets data
15:55:41<quicksilver>fracture: indeed, threads use unix select behind the scenes.
15:55:55<mux>also, haskell threads are very, very, veeeery cheap.
15:55:57<fracture>what do they use on windows?
15:55:57<quicksilver>so threads are the "simplest" way to get select-like behaviour
15:56:07<quicksilver>some windows API whose name escapes me
15:56:13<fracture>WaitForMultipleObjects?
15:56:16<mux>WaitForMultipleEvents or something
15:56:19<quicksilver>WaitForNextThingyWotsitBuriedDeepInSomeUglyAPI
15:56:20<mux>heh, yeah
15:56:43<fracture>so... if I were writing say a telnet client
15:56:48<fracture>I'd want a thread for interaction with the user
15:56:53<fracture>and a thread for interaction with the remote host
15:56:53<fracture>?
15:56:56<mux>yup
15:56:58<fracture>ok
15:57:00<quicksilver>probably four
15:57:03<fracture>I'll learn about threads now :)
15:57:06<mux>each blocking on its file descriptor
15:57:08<fracture>four?
15:57:10<quicksilver>hmm
15:57:17<mux>and you'll probably have a third one to manage the rest
15:57:21<quicksilver>maybe just three.
15:57:25<fracture>ahh I see
15:57:26<fracture>ok
15:57:27<quicksilver>at least two threads for the socket.
15:57:27<mux>that will be blocking on MVar's or Chan's
15:57:48<quicksilver>(so reading and writing don't accidentally block each other)
15:58:06<fracture>ok
15:58:23<mux>in the case of a telnet client, I think you can actually get away with only two threads
15:58:25<fracture>and... I'm hoping the referential transparency stuff probably simplifies MT correctness a lot in haskell, eh?
15:58:39<quicksilver>yes, hugely
15:58:48<fracture>(the idea of using threads for something like this in other languages would be pretty scary, from a reliability perspective)
15:58:50<quicksilver>everything is immutable and can be safely shared between threads
15:58:54<fracture>cool, sounds good
15:59:00<mux>the one blocking on the socket will just putStrLn stuff when it has some, and the thread blocking on the keyboard input will write to the socket when it has lines to send
15:59:12<Beelsebob>fracture: note though – while executing an IO action you don't have referential transparency
15:59:13<fracture>makes sense
15:59:20<Beelsebob>so, be careful still ;)
15:59:25<quicksilver>Beelsebob: eh?
15:59:27<quicksilver>Beelsebob: what?
15:59:28<fracture>I might actually try a telnet client first to make sure I grok all this (should be pretty quick to whip up)
15:59:38<Beelsebob>quicksilver: creating IO actions is pure, running them is not
15:59:51<quicksilver>Beelsebob: what's that got to do with referential transparency.
16:00:00<quicksilver>haskell is referentially transparent, inside IO and out.
16:00:08<fracture>quicksilver: well, you could communicate with side-effects by putting data on the filesystem
16:00:15<Beelsebob>yes, but the haskell runtime evaluating an IO action does not
16:00:16<fracture>(that's what you mean, right beel?)
16:00:21<Beelsebob>you don't get the same result from getChar every time
16:00:24<fracture>you could get deadlocks that way if you tried
16:00:27<quicksilver>Beelsebob: referential transparency is a static property.
16:00:31<quicksilver>it applies to code
16:00:32<quicksilver>terms
16:00:33<quicksilver>expressions
16:00:35<quicksilver>not running code.
16:00:41<quicksilver>All of haskell is referentially transparent
16:00:43<quicksilver>including IO
16:00:49<quicksilver>"getChar" always denotes the same thing
16:00:50<Beelsebob>quicksilver: yes, it's a static property of Haskell, but not of the programs that IO based code generates
16:00:52<quicksilver>(an IO action)
16:01:01<fracture>quicksilver: that is definitely not how I understand that terms "referentially transparent"
16:01:03<Beelsebob>the IO action you get back, is not referentially transparent
16:01:12<quicksilver>ACTION counts to 10, slowly.
16:01:33<quicksilver>Beelsebob: it is absolutely meaningless to say "...not of the programs that IO based code generates".
16:01:47<quicksilver>referential transparency is a property of terms - or source code.
16:02:11<Beelsebob>it's a property of a program - and when we use IO we talk about two programs
16:02:15<Beelsebob>the one we write in haskell
16:02:16<quicksilver>it is not meaningful to discuss if a compiled program is referentially transparent.
16:02:24<Beelsebob>and the one it generates and causes the runtime to execute
16:02:45<quicksilver>I am very sorry. I do not have time to have this argument with you now.
16:02:51<quicksilver>Some time later when I have more time, perhaps.
16:03:14<kynky>haskell communcating with world full of side effects
16:03:25<quicksilver>However, lest anyone else in the channel get confused, haskell *is* referentially transparent, and Beelsebob, much as I respect him, and value his friendship, is quite wrong here.
16:03:35<tromp>evaluating getChar just gives you getChar, it's already evaluated. executing it is something quite different
16:03:45<Beelsebob>quicksilver: note – I'm not claiming haskell isn't RT
16:03:53<Beelsebob>I'm claiming that the programs it generates are not
16:04:07<tromp>so in terms of evaluation yeielding substitutable values, it is perfectly RT
16:04:13<Beelsebob>IO actions are not RT
16:04:15<Beelsebob>Haskell is
16:04:17<Ferdirand>what does it mean for a program not to be RT ?
16:04:29<Ferdirand>it cannot be substituted with its output ?
16:04:35<Beelsebob>Ferdirand: indeed
16:04:41<tromp>it's not evaluation that gives its output
16:04:44<kynky>IO is just a special case of Monad ?
16:04:55<Beelsebob>kynky: it's a secret special case that has hooks into the runtime
16:05:12<ski>"referentially transparent" is about being able to replace variables with the expressions they're defined as
16:05:28<fracture>I don't see how IO could be considered RT if it can change filesystem state
16:06:03<opqdonut>there's a trick to it
16:06:04<tromp>the real IO takes place outside of haskell's evaluation
16:06:05<Philonous>I wonder whether unsafePerformIO is referentially transparent or not haskell.
16:06:09<fracture>what's the difference between evaluating and running IO actions?
16:06:15<Beelsebob>fracture: IO code in Haskell generates an action
16:06:18<ski>one may replace variables of type `IO Whatever' with their defining expressions in exactly the same way as variables of other types
16:06:19<Beelsebob>and that action is always the same action
16:06:20<opqdonut>fracture: openFile "asdf" is always the same action
16:06:29<Beelsebob>the action however, is itself not RT
16:06:44<ski>the action is a value
16:06:47<kynky>the consequence of the action
16:06:49<opqdonut>fracture: you could interpret a haskell program as producing a tree of IO operations and reactions to them
16:06:58<Beelsebob>ski: programs are values too
16:06:59<opqdonut>fracture: the production of the tree is pure
16:06:59<Ferdirand>why not ? the effects of an action are not its values, right ?
16:06:59<Beelsebob>;)
16:07:14<ski>Beelsebob : you mean the `main' action ?
16:07:35<Beelsebob>Ferdirand: take for example the unsafeLaunchMissiles function – when run, it has side effects - it itself is not RT
16:07:38<Beelsebob>*however*
16:07:47<Beelsebob>the unsafeLaunchMissiles function is always the same value
16:07:55<Beelsebob>so a program that refers to it and passes it around *is* RT
16:08:12<fracture>is "actions" a concept applicable to other monads? (I thought I understood monads by now... guess not)
16:08:18<Beelsebob>fracture: no
16:08:20<fracture>meaning, a distinction between evaluating and running them
16:08:22<kynky>the program, and the system the program runs on ?
16:08:26<fracture>ok
16:08:28<Beelsebob>an "action" is a secret runtime thing that's magical
16:08:35<fracture>I see
16:08:40<Beelsebob>it's applicable only with the IO monad
16:08:51<SamB>Beelsebob: well ... not quite!
16:09:10<ski>fracture : yes :) `action' is applicable to every monad
16:09:11<SamB>STM, for instance ...
16:09:33<ski>e.g. here's an action in the list monad
16:09:37<SamB>maybe ST
16:09:49<SamB>have similar magical runtime secret things
16:09:50<ski>> [(+),(*)] `ap` [2,3] `ap` [4,5]
16:09:51<lambdabot> [6,7,7,8,8,10,12,15]
16:10:24<fracture>(where's ap defined?)
16:10:29<ski>@index ap
16:10:30<lambdabot>Control.Monad, Control.Monad.Reader, Control.Monad.Writer, Control.Monad.State, Control.Monad.RWS, Control.Monad.Identity, Control.Monad.Cont, Control.Monad.Error, Control.Monad.List, Data.Graph.
16:10:30<lambdabot>Inductive.Query.ArtPoint, Data.Graph.Inductive.Query, Data.Graph.Inductive
16:10:30<opqdonut>fracture: you can think of things in the State monad as actions too
16:10:39<opqdonut>fracture: you run them with execState
16:10:39<ski>`Control.Monad', really
16:10:44<ski>@src ap
16:10:44<lambdabot>ap = liftM2 id
16:10:51<opqdonut>of course, running the other monads is doable with a pure function
16:10:58<gwern>ಥ_ಥ beautiful
16:11:16<opqdonut>there are many metaphors for monads. which ones are most applicable depends on the situation
16:11:27<fracture>ski: what makes that an action?
16:12:12<ski>fracture : it having a type of form `M Foo' for a type constructor `M' (here `[]') being an instance of `Monad'
16:12:40<EvilTerran>ACTION talks about actions in monads other than IO
16:13:21<fracture>ok so, "action" is either a metaphor for understanding what monads do, or a part of the implementation details of the IO monad.... (or both)?
16:13:40<Saizan>the former
16:13:43<fracture>when I write a user defined monad though, there doesn't seem to be a separate evaluation step vs. "run the actions" step
16:14:19<fracture>ok... so how can IO be referentially transparent at evaluation time then?
16:14:24<ski>(imo whether a monad is defined (wrt some implementation) in haskell or not isn't that important (here). the important part is that it obeys the same reasoning laws as all the rest of haskell)
16:14:31<Beelsebob>fracture: because those two steps are seperate
16:14:33<Beelsebob>first you evaluate
16:14:36<Beelsebob>and you get an action
16:14:41<Beelsebob>that action is always the same action
16:14:45<Beelsebob>then you run the action in the runtime
16:14:48<roconnor>@wiki IO_Semantics
16:14:48<lambdabot>http://www.haskell.org/haskellwiki/IO_Semantics
16:14:50<Beelsebob>the action itself is not RT though
16:15:02<ski>ACTION disagrees with Beelsebob
16:15:04<fracture>can I manipulate IO actions in code?
16:15:07<Saizan>Beelsebob: that's confusing
16:15:26<Saizan>you can pass IO actions around as the other values, yes
16:15:27<fracture>(if they are purely an implementation detail of the compiler, I think that makes no sense, and we should call IO non-referentially transparent)
16:15:54<roconnor>ACTION kinda agrees with Beelsebob
16:16:07<fracture>can you give an example saizan? (sorry if I'm being dense; just trying to grok)
16:16:12<Ferdirand>but you cannot run an action from haskell code
16:16:19<Beelsebob>no, sure
16:16:23<Beelsebob>that's why Haskell is RT
16:16:23<Saizan>Ferdirand: for example replicateM
16:16:28<Saizan>?type replicateM
16:16:29<lambdabot>forall (m :: * -> *) a. (Monad m) => Int -> m a -> m [a]
16:16:41<Beelsebob>we use main to create an IO action and the runtime happens to run it for us as well
16:16:55<Saizan>fracture: that takes a number and an action and performs it that number of times
16:17:32<dmwit>A value of type "IO a" is a description of how to generate a value of type "a", perhaps doing some IO in the process.
16:17:35<Ferdirand>no, that builds a new action that when performed, will perform the other a number of times
16:17:41<dmwit>It can be referentially transparent because it is always the same description.
16:17:45<ski>executing `IO'-actions may cause "effects" to happen. in most languages, these would be "side-effects", while in haskell they're not, because the effects are accounted for in the types - you can't use an `State Foo Int' in place of an `Int' or vice versa (similarly for any other monad than `State Foo')
16:17:53<dmwit>But following its instructions can produce different values.
16:17:56<Saizan>Ferdirand: yeah, right
16:18:00<Beelsebob>dmwit: no no - that would be the program *generating* the IO action that's referentially transparent
16:18:07<Beelsebob>the description itself is not RT
16:18:24<Beelsebob>otherwise all C programs would be RT - after all, it's always the same program you're running
16:18:24<dmwit>Sure, I'm fine with that distinction.
16:19:06<dmwit>That's not how the term RT is usually used, I think, but it's a fine way to use it if you're consistent.
16:19:08<ski>in the same way as `IO'-effects, we can talk about `State Foo'-effects, `Cont Answer'-effects, and even `[]'-effects and `Parser Token'-effects
16:19:14<Saizan>Beelsebob: i think you're mixing layers
16:19:35<dmwit>(i.e. usually we would say the "IO a" value is RT because we can refer to it many times, and it is still the same value, i.e. the same description.)
16:19:37<Beelsebob>ski: yes, but those ones actually always will give the same value when run
16:19:40<Beelsebob>unlike IO actions
16:19:53<Saizan>Beelsebob: i can subsitute the description for the expression that evaluates to it anywhere
16:19:57<ski>Beelsebob : "run" isn't well-defined here, i'd claim
16:20:13<Beelsebob>Saizan: sure - that makes the program generating the description RT
16:20:21<Beelsebob>what you can't do, is substitute the value that the description computes for the description
16:20:24<fracture>Saian: ok that seems to make sense (w/ the replicate)
16:20:27<Beelsebob>so the description is *not* RT
16:20:39<fracture>is there a function that just runs an IO action?
16:20:56<dmwit>But the value the description computes doesn't even have the same type!
16:21:00<Saizan>fracture: no
16:21:06<dmwit>Of *course* you can't substitute it for the description itself.
16:21:13<fracture>@src replicateM
16:21:13<lambdabot>replicateM n x = sequence (replicate n x)
16:21:26<dmwit>fracture: Yes, but we don't use it. ;-)
16:21:29<ski>(Beelsebob : in Clean, one can easily imagine `IO a' being implemented as `*World -> (a,*World)', would you claim such an `IO'-action to not be RT, as well ?)
16:21:47<SamB>doesn't the description compute the program ?
16:22:03<Beelsebob>ski: sure - but that's not in any way useful - if you want nice strong guarentees about how the program behaves, you don't want to have to think about how the world behaves too
16:22:11<SamB>I wish you'd stop saying RT, I keep thinking of Real Time
16:22:19<Beelsebob>and as we were talking about whether RT helps with threading using forkIO, that's pretty useless
16:22:34<Beelsebob>RT helps with threading, as long as the threading happens in the RT bit, not in the description
16:22:49<fracture>ok so.... something like putStrLn is referentially transparent, because it always returns the same action. But sequence or replicateM or main (anything that runs actions) is not RT.
16:22:51<fracture>correct?
16:22:58<ski>Beelsebob : the point of defining such an `IO' would be to not "have to think about how the world behaves" .. just as with haskell's `IO'
16:23:03<SamB>referential transparency helps a lot with threading
16:23:13<quicksilver>RT helps enormously with threading.
16:23:17<quicksilver>and there is no RT bit.
16:23:19<Saizan>fracture: sequence is still RT
16:23:21<quicksilver>all of haskell is RT
16:23:21<Beelsebob>sure it helps with threading
16:23:21<dmwit>fracture: replicateM is RT
16:23:25<quicksilver>there is no "bit" which is not.
16:23:26<Beelsebob>what it doesn't help with is forkIO
16:23:30<quicksilver>(sorry, I know I said I didn't have time)
16:23:30<quicksilver>;)
16:23:32<Beelsebob>because forkIO is not threaded
16:23:35<SamB>if most of your computations are done in referentially transparent code, you have a heck of a lot less mutation to worry about the interactions between ...
16:23:37<fracture>how can it be RT if it runs actions that have side effects?
16:23:42<Beelsebob>it's an action that happens to generate threads
16:23:45<Saizan>fracture: they just build bigger actions out of smaller ones
16:23:53<dmwit>fracture: It doesn't run actions that have side effects, that's the thing.
16:24:00<ski>(Beelsebob : my point there was that haskell's `IO' could have been defined in haskell, provided lower primitives in terms of `*World' was given, and provided haskell had uniqueness types)
16:24:09<jacobian>hmmm, if I use the error monad it serialises in such a way that the computation doesn't terminate. Is there some way to do errors that wont have this problem?
16:24:10<SamB>fracture: only if the side effects end up cancelling out ...
16:24:15<SamB>or something like that
16:24:26<Beelsebob>ski: sure – but then you have to think about "World" when dealing with your values - and you're back at square one with threading being hard
16:24:32<fracture>ok... so only main is not RT?
16:24:32<dmwit>fracture: replicateM takes a description of how to build an "a" value and returns a description of how to return several "a" values in a list.
16:24:33<Beelsebob>if all threading does is manipulate the "world"
16:24:36<Saizan>fracture: only the action corresponding to main gets run
16:24:47<SamB>for instance, RT code is allowed to use dynamically allocated memory
16:24:47<Saizan>fracture: but that doesn't mean main is not RT
16:24:53<ski>(Beelsebob : these lower-level primitives might be defined in C or some assembler .. but the same may be true of `cos' .. what matters is what modes of *reasoning* is allowed)
16:25:13<Beelsebob>ski: but they're not allowed - they're no easier when talking about IO code than when talking about C code
16:25:23<ski>Beelsebob : no, the point of defining an abstract data type `IO' is exactly *not* to have to think about `World'
16:25:30<Beelsebob>they're easier when talking about magically parallelising things because we're not affecting the world
16:25:35<Beelsebob>but they're not easier in IO at all
16:25:47<roconnor>Nothing in Haskell runs any actions. The only thing that runs actions in the "run-time system" which runs the action called main (which is probably has been built up from lots of little actions), and the "run-time system" isn't accessible inside Haskell
16:25:51<Philonous>Beelsebob: If haskell ist RT, what about unsafePerformIO? Clearly let a = unsafePerformIO ( randomIO ) can not be replaced with a value, because haskell is not lazy after all
16:25:54<SamB>Beelsebob: um, IO code is a lot easier than C code
16:26:06<Beelsebob>SamB: what extra guarentee do you get?
16:26:10<Beelsebob>when it comes to threading?
16:26:24<roconnor>unsafePerformIO isn't part of Haskell. It is part of GHC, and other perhaps implementations.
16:26:25<dmwit>Philonous: SSSHHHH! You're not helping.
16:26:31<SamB>Beelsebob: well, a lot of the function calls in your IO code can be plainly seen to not involve IO
16:26:37<SamB>that helps
16:26:46<SamB>so you only have to look at the ones that do
16:26:51<Beelsebob>SamB: that's not what I asked – that's a case of non-IO code is nice to reason about
16:26:55<SamB>in C, any of them code!
16:26:59<Beelsebob>that's not a guarentee that you get in IO code, but not in C
16:27:01<SamB>er. could
16:27:10<dmwit>Philonous: We've even consciously avoided that when he asked whether there was a function that just runs an IO action. ;-)
16:27:11<SamB>Beelsebob: sure it is!
16:27:12<Beelsebob>that's a guarentee you get by *not* using IO
16:27:32<SamB>what I'm saying is that IO isn't all-or-nothing, which is really nice
16:27:42<Beelsebob>sure - but that doesn't make it easy to reason about IO
16:27:44<SamB>in C, it's all C ...
16:27:47<Saizan>it's a guarantee you get by the existence of IO, that let you make a distinction
16:27:48<Beelsebob>it makes it easy to reason about things that aren't IO
16:27:55<Beelsebob>IO is no easier to reason about than C code
16:27:59<SamB>Beelsebob: well, it cuts down the stuff you need to be careful about
16:28:07<fracture>it's seeming harder so far
16:28:09<SamB>it's a reason to use IO instead of C ...
16:28:14<Beelsebob>SamB: again -- that's not something that IO gives you
16:28:18<Beelsebob>it's something that *not* using IO gives you
16:28:29<fracture>so, I need to change my mental model here is what it sounds like
16:28:39<SamB>well, it's something Haskell gives you ...
16:28:44<Beelsebob>sure
16:28:57<Beelsebob>but that doesn't make reasoning about threading code in IO any easier than reasanoing about threading code in C
16:28:59<Beelsebob>...
16:29:06<Beelsebob>it makes reasoning about *pure* code easy
16:30:24<SamB>yeah, well, IO has that advantage over C
16:30:29<Beelsebob>no
16:30:31<fracture>so in practice, does the program really build this action tree before executing?
16:30:33<Beelsebob>pure code has that advantage over C
16:30:34<SamB>you don't have to use it everywhere!
16:30:41<Beelsebob>I don't have to use C everywhere
16:30:45<Beelsebob>I can make FFI calls into Haskell
16:30:47<dmwit>fracture: Yes, but lazily.
16:30:52<fracture>I see
16:30:57<SamB>it can invoke pure code, and you can tell AT A GLANCE when it does
16:30:57<Beelsebob>in fact, if we consider IO in Haskell to be referentially transparent, then IO actions like forkIO are not multi threaded by nature – we can use a single thread to evaluate the IO action that contains the instruction to fork a new thread
16:31:04<TomMD>dcoutts: Did you ever get the hackage patches I sent? I sent them again just now just in case.
16:31:17<fracture>and the value of main is an action, composed of other actions... this sorta makes sense
16:31:19<Beelsebob>so it's totally useless to talk about threading being easy to reason about in haskell if we consider haskell to be RT
16:31:23<SamB>you CAN write pure code in C; you can even annotate it as such.
16:31:28<Saizan>fracture: if by "in practice" you mean "how GHC implements this" then no, but you shouldn't care
16:31:31<ski>in some sense, the point of using monads for traditional effects (state, i/o, exceptions, environment/reader, output/writer, continuations, angelic nondeterminism, demonic nondeterminism, ...) is to know when you're *not* using a certain kind of effect
16:31:35<Beelsebob>SamB: or... I can make an FFI call into some pure Haskell code
16:31:36<SamB>but what you can't do is tell at a glance from the call site that it's pure!
16:31:43<quicksilver>Beelsebob: reasoning about threaded code in haskell is about a million times easier than reasoning in C
16:31:53<Beelsebob>quicksilver: exactly how
16:31:54<quicksilver>Beelsebob: the main reason being that data is immutable and safely shared.
16:32:04<quicksilver>it's still not easy, but it's at least a million times easier.
16:32:07<Beelsebob>no it's not
16:32:13<Beelsebob>ACTION points at the iORef
16:32:18<SamB>Beelsebob: you can't mutate a cons cell
16:32:21<SamB>that helps!
16:32:27<Beelsebob>SamB: yes - *pure* code again
16:32:27<quicksilver>in C someone can modify one byte of a word when you're halfway through reading it.
16:32:28<Beelsebob>not IO code
16:32:33<Beelsebob>IO code however car do mutation
16:32:38<lilac>Beelsebob: when you said earlier that haskell's not referentially transparent when running IO actions, presumably you meant that you can say "do forkIO $ evilUnsafePointerFiddling; let { x = pureThing; y = pureThing }; return (x, y)"
16:32:38<mreh>can I implement the exponential operator in pure code?
16:32:38<Beelsebob>ACTION points at the IORef again
16:32:39<Saizan>Beelsebob: you don't use IORef everywhere in IO code either
16:32:42<SamB>Beelsebob: IO code can't mutate a cons cell either, though
16:32:47<quicksilver>you don't even use IORef mostly.
16:32:49<Beelsebob>lilac: I never said that
16:32:51<quicksilver>you use it very sparingly.
16:32:54<Beelsebob>I said that the IO action is not RT
16:32:56<lilac>... and have it be different from " ... let { x = pureThing; y = x }; ..."
16:32:57<Philonous>quicksilver: If you say haskell is referentially transparent, does that include unsafePerformIO or is that function not haskell (but a compiler extension)
16:32:57<quicksilver>and never with threads.
16:33:04<quicksilver>Philonous: it's not even a function.
16:33:12<SamB>so, you can tell WHAT code could mutate stuff, and WHAT things could possibly be mutated
16:33:17<quicksilver>Philonous: it's a compiler primitive which breaks everything about the language which is good.
16:33:23<lilac>Beelsebob: pity, because i was going to agree with you :)
16:33:47<lilac>inside the IO monad, you can tell how a pure function was written
16:33:48<Beelsebob>lilac: well, evilUnsafePointerFiddling isn't part of Haskell
16:33:49<SamB>it reduces the places you have to pay attention to by about 99% ...
16:33:55<Philonous>quicksilver: Right it's not a function. But it's there and I wonder if this is haskell or not
16:33:57<lilac>Beelsebob: is the FFI part of haskell?
16:34:12<lilac>what do you call 'Haskell' here?
16:34:12<Beelsebob>lilac: yes, but everything's wrapped up in an IO type
16:34:20<Beelsebob>so that's all safe
16:34:21<lilac>Beelsebob: yes, my do-block was in IO
16:34:23<lament>gets() is not part of C!
16:34:23<SamB>lilac: yeah, mutating cons cells by using unsafe pointer manipulations is NOT done in any serious code ...
16:34:32<Beelsebob>lilac: well then your two programs don't have the same type
16:34:34<TomMD>Beelsebob: IORef is a poor example for your argument - I use it in threaded code all the time. Once I read the IORef I know the data structure won't change - sure the IORef might get updated with a newer piece of information but the copy I have is _new enough_ that my opertions can continue... and the copy I have won't change, a promise I wouldn't have in C.
16:34:36<lilac>SamB: no, absolutely not.
16:34:37<Beelsebob>quicksilver: okay, so... Haskell is easy to do multithreading – if you avoid all the nasty parts of it
16:34:39<lilac>Beelsebob: yes they do...
16:34:40<SamB>lilac: Linus would never allow such things in his tree ;-P
16:34:44<Beelsebob>which is roughly what I was trying to say
16:34:51<Beelsebob>it's not inhearantly easier in Haskell
16:34:57<Beelsebob>it's just easier to dodgy the nasty things
16:35:00<Beelsebob>dodge*
16:35:06<lilac>Beelsebob: they're both :: IO (x, y) for some x and y
16:35:10<Guest39336>anyone know if those libs for updating record fields kill any performance optimizations or rewrite rules?
16:35:20<Beelsebob>lilac: then they both return the same IO action every time
16:35:22<Beelsebob>and are RT
16:35:31<lilac>Beelsebob: it's not the IO action i'm looking at
16:35:36<Beelsebob>the IO actions that are run by the runtime when you evaluate the Haskell program is not RT though
16:35:57<quicksilver>Beelsebob: it *is* inherently easier.
16:35:58<lilac>Beelsebob: the IO action invokes some pure code, and that pure code can produce different results for the same input depending on what evils the IO code surrounding it does
16:36:08<quicksilver>it's inherently easier because data is immutable
16:36:08<Beelsebob>quicksilver: sure – but it needs some qualification
16:36:13<lilac>Beelsebob: given all Haskell code is surrounded by IO code I consider this to be an issue
16:36:16<Botje>Guest39336: why, are you running into problems?
16:36:16<quicksilver>I don't understand what's so controversial about that.
16:36:19<TomMD>Guest39336: Its just sugar so it shouldn't harm anything compared with rebuilding the structure by hand.
16:36:19<Beelsebob>threading is not easier in Haskell
16:36:24<quicksilver>yes it is.
16:36:24<SamB>the dangerous things in Haskell mostly have yellow-and-black stripes on them, and there is much less need to use them than in C -- C doesn't have any other option in most cases.
16:36:29<Beelsebob>threading is easier in a subset of haskell that's inherantly safe
16:36:35<quicksilver>I have programmed using threads in quite a few languages
16:36:44<quicksilver>and it honestly is much easier in haskell
16:36:47<ski>in Mercury, there's a `promise_pure' construct that can be used on code the implements a pure inferface (regardless of implementation details). if one lies to the compiler, all bets are off. it would be nice if (e.g.) GHC would give similar guarrantees about `unsafePerformIO' (or similar)
16:36:52<quicksilver>(than C, C++, Java for example)
16:37:01<Saizan>Beelsebob: how the language is normally, and most naturally used does have an importance in such discussions
16:37:09<jkramer>Hello
16:37:16<fracture>thanks for all the help grokking that all (gotta go play scrabble now... haha)
16:37:18<opqdonut>ski: indeed, something like how unsafePerformIO is used in unamb
16:37:21<Beelsebob>Saizan: true – and I'd 100% agree if we consider the naturally part
16:37:29<Beelsebob>but completelly disagree if we consider the normally part
16:37:29<Guest39336>TomMD: are you talking about the haskell98 accessors?
16:37:33<opqdonut>er, insert "for" into previous sentence
16:37:37<jkramer>How can I kill a thread in Haskell?
16:37:44<opqdonut>:t killThread
16:37:44<Beelsebob>because the normal use of Haskell involves all sorts of crazy calls out to other languages, and weird shit going on
16:37:45<lambdabot>Not in scope: `killThread'
16:37:48<opqdonut>gah
16:37:56<Saizan>Beelsebob: why? we don't write datastructures with mutable variables at every node
16:37:57<Guest39336>Botje: nah no problems yet just curious before i change code to use it
16:38:13<jkramer>Are you sure? The description if killThread sounds like it doesn't really kill it
16:38:19<Saizan>Beelsebob: and that's exactly what makes threading much easier
16:38:20<TomMD>Guest39336: I was talking about the record field updating, which I believe is just sugar. i.e. let newFoo = Foo { fieldOne = x }
16:38:31<TomMD>jkramer: It kills it.
16:38:32<Beelsebob>Saizan: certainly if we're writing naturally – however, I suspect the majority of packages on Hackage involve a large amount of crazyCallToCBecauseI'mBindingStuff
16:38:35<opqdonut>jkramer: anyway, killThread :: ThreadId -> IO ()
16:38:46<opqdonut>ah, you were talking about it already
16:38:53<jkramer>And how do I get the ThreadId?
16:38:59<TomMD>@type forkIO
16:38:59<Beelsebob>so naturally - yes
16:39:01<lambdabot>Not in scope: `forkIO'
16:39:01<Beelsebob>normally - no
16:39:03<TomMD>grrr
16:39:05<ski>opqdonut : yes, and in variouse byte-string implementations too, iirc .. it would be nice if the implementations could rely on more than the optimizer in GHC not currently botching it up (cf. `NO_INLINE' nonsense)
16:39:06<dmwit>jkramer: from forkIO
16:39:08<opqdonut>jkramer: you got it from forkIO
16:39:14<opqdonut>:t Control.Concurrent.forkIO
16:39:15<lambdabot>IO () -> IO GHC.Conc.ThreadId
16:39:19<Saizan>Beelsebob: bindings are quite a different thing, and most provide an RT interface
16:39:20<opqdonut>qualified works
16:39:22<jkramer>And inside the thread?
16:39:28<Beelsebob>Saizan: most?
16:39:29<Beelsebob>o.O
16:39:33<lament>Beelsebob: probably because the majority of useful packages on hackage are library wrappers, but surely that's not the way to judge a language
16:39:33<Beelsebob>dunno which you've looked at
16:39:41<opqdonut>ski: yeah
16:39:41<Beelsebob>I think I've only met 1 binding that provided an RT interface
16:39:47<Saizan>Beelsebob: which have you looked at?
16:39:52<Beelsebob>OpenGL is a good start
16:39:55<dmwit>jkramer: Inside the thread, you can just die, you don't need to commit suicide.
16:39:59<Beelsebob>wanna try using that + threading?
16:40:05<Beelsebob>or GLUT
16:40:14<lament>Beelsebob: if you judge haskell by what's in library bindings, that's like saying you can't write a useful program in the language itself :)
16:40:15<dmwit>jkramer: However, all the usual methods of inter-thread communication work here, in case you really want to kill your own self.
16:40:16<Beelsebob>or any of the graphics/UI packages for that matter
16:40:21<Saizan>ah, ok, i've never worked with graphics
16:40:30<Saizan>but that's a peculiar subset, i'd think
16:40:32<jkramer>dmwit: I just want the thread to disappear :)
16:40:45<dmwit>jkramer: It disappears when it stops running.
16:40:49<jkramer>exitSuccess seems to work, but I'm not sure if it's intended to be used in threads
16:41:05<Beelsebob>Saizan: maybe for natural code – but I don't think so for "normal" people – I know very few coders who don't at some point have to write a UI
16:41:25<TomMD>Outside of graphics you don't run into such issues as GLUT or OpenGL... take the OpenSSL, Network, XML, and Xen bindings as examples.
16:41:26<dmwit>jkramer: forkIO (return ()) -- does not strand any threads or anything, that thread just "disappears"
16:41:28<Saizan>graphic toolkits tend to impose you a mainloop, even, right?
16:41:37<Beelsebob>Saizan: some of them, yeh
16:41:40<Beelsebob>(most?)
16:41:52<Guest39336>glfw doesnt
16:42:06<Beelsebob>Saizan: I don't know of one single one that's thread safe though
16:42:10<Beelsebob>nor one that's RT
16:42:21<Saizan>well, there's lot of networking where concurrency is important that's quite far from GUIs
16:43:01<TomMD>Indeed, graphics are unique in their terrible use of TLS.
16:43:18<Philonous>@type myThreadId -- jkramer
16:43:19<lambdabot>Not in scope: `myThreadId'
16:43:25<Beelsebob>which is a shame... because graphics is one of the main areas where RT is *most* beneficial
16:43:29<TomMD>@type Control.Concurrent.myThreadId
16:43:31<lambdabot>IO GHC.Conc.ThreadId
16:43:42<Beelsebob>because we have lovely hardware that can run 1600 threads at once
16:43:58<jkramer>Philonous: Great, thanks :)
16:44:11<lament>my computer can only run two threads at once :(
16:44:22<ski>a binding not providing an RT interface would be similar to calling `unsafePerformIO' on specific impur `IO'-actions .. if the bindings bind side-effecting actions into haskell `IO', and (roughly) don't mutate values which can be "inspected" in haskell without using `IO', then it should be RT
16:44:41<TomMD>I think Beelsebob is talking about GPUs, which is somewhat conflating the issue if that's the case.
16:45:14<ski>of course, an `IO'-intersive binding would be an *imperative* (/ effectful) interface .. but still RT
16:45:28<mightybyte>Is there an easy way to have cabal-install rebuild all dependencies with profiling enabled?
16:45:49<alexsuraci>oi, neither hsql nor hdbc seem to work with the latest ghc
16:45:54<Saizan>mightybyte: nothing automatic
16:46:03<ski>this is similar to how an `State Foo'-based solution for a problem is imperative/effectful
16:46:13<alexsuraci>hsql gives me a segfault, hdbc errors with "schedule: re-entered unsafely"
16:47:22<TomMD>alexsuraci: If you're using the hsql package, I think haskelldb (and thus haskelldb-hsql) are the recommended DB libraries these days.
16:48:08<alexsuraci>TomMD: I'd go further with HaskellDB if I could find some decent documentation on it. Plus if it uses hsql and hsql is "broken" it's doubtful I'd have much luck there. :/
16:48:48<TomMD>alexsuraci: It could potentially use it safely, but admitadly I haven't used the DB libraries in a while.
16:55:54<mightybyte>Saizan: Hmm, that seems like a pretty significant omission.
16:59:12<Athas>Where do I get the profiling libraries for binary-0.4.4?
17:00:19<mux>Athas: you have them by building the package with profiling libraries enabled
17:00:33<mux>Athas: you can do that by passing the -p flag to the configure command (of cabal)
17:00:38<mux>ie runhaskell Setup.hs configure -p
17:01:29<Athas>mux: I think I used 'cabal install binary' to get them (at least they seem to be installed locally). Can I do that with cabal install?
17:01:55<mux>there's most likely a similar flag to use, but I don't know it
17:03:35<Athas>Where can I find a manual for cabal-install? It didn't install any manpages.
17:04:22<mux> -p --enable-library-profiling Enable Library profiling
17:04:26<mux>from cabal help install
17:04:32<Athas>Thanks.
17:04:34<mux>so you can pass the very same flag
17:08:06<tibbe>@seen bos
17:08:06<lambdabot>bos is in #haskell-in-depth, #ghc and #haskell. I don't know when bos last spoke.
17:08:54<philipp_>i'm using parMap to parallelise a job which works fine for half an hour (cpu is constantly at 180%) but after that it drops to ~100% for the remaining 2 hours, any ideas?
17:09:41<tibbe>philipp_: does profiling output give anything? i.e. is lots of time spent in GC?
17:10:10<philipp_>tibbe: have to check that...
17:10:20<philipp_>what if so?
17:10:30<tibbe>philipp_: don't remember the exact flag
17:10:41<tibbe>philipp_: if there's excessive GC you need to figure out why ;)
17:10:45<tibbe>i.e. profile
17:12:41<lilac>philipp_: does your list have two entries, one of which takes 5x longer to process than the other, by any chance? :)
17:14:14<jkramer>Is there a way to work around circular module imports?
17:15:05<jkramer>I have two modules and both use functions from the other module
17:15:30<roconnor>jkramer: usually you can pull apart modules further to break the cycle.
17:15:48<roconnor>jkramer: for example putting one of those functions into it's own module
17:16:00<lilac>philipp_: http://www.nabble.com/Control.Parallel.Strategies.parMap-CPU-usage-td22497395.html
17:16:15<roconnor>jkramer: then just re-export it from the module you originally wanted it in.
17:16:24<saynte>jkramer: you can define a the necessary function in interface files, hs-boot i think. but you have to do this manually.
17:17:03<dons>ACTION ponders why the 'probability monad' post is at the top of programming reddit.
17:18:05<mux>reddit is being weird today
17:19:29<philipp_>lilac: thanks, so I'll try the head revision
17:22:45<voker57_>how to convert numbers between bases?
17:22:58<JamesSanders>I keep get this error in one of my programs "Not in scope: type constructor or class `True'"
17:23:11<kpreid>JamesSanders: True is not a type; it is a value.
17:23:36<Twey>voker57_: That is not a valid question
17:23:51<Twey>Numbers are simply numbers; they have no associated base until they're formatted for human reading
17:24:30<Twey>(which can be done with Numeric.showIntAtBase, as well as several small helper functions for common cases like Numeric.showHex)
17:25:07<Botje>#haskell: we fix your question _AND_ answer it!
17:25:16<mightybyte>How do you do a ghc build with profiling when it tells you "You need to build the program twice...using -osuf"?
17:25:33<JamesSanders>so when something calls for Bool then I should be able to use True right?
17:25:41<JamesSanders>@type True
17:25:41<lambdabot>Bool
17:27:45<kpreid>JamesSanders: Yes, but you can't give it a *type* True
17:28:10<kpreid>JamesSanders: The difference between True and other Bools (i.e. False) does not show up at the type level.
17:28:18<kpreid>If that's still confusing, show us your code
17:31:19<Beelsebob>kpreid: sure it does... look... data True; data False
17:31:38<Twey>ACTION twitches.
17:31:44<Beelsebob>>.>
17:31:45<Beelsebob><.<
17:32:15<JamesSanders>so there is a Conf constructor and it looks a bit like this Conf = Conf {
17:32:15<JamesSanders>priority :: !Bool
17:32:15<JamesSanders>groupMembership :: !Bool
17:32:53<JamesSanders>and my code is like so : conf = Conf True True
17:33:08<JamesSanders>what am I doing wrong?
17:33:09<kpreid>That's fine.
17:33:19<Beelsebob>looks good to me :)
17:33:24<kpreid>There's something else wrong.
17:33:25<JamesSanders>yeah but it throws those errors in ghci
17:33:37<Saizan>it must be something else
17:33:42<ski>@paste
17:33:43<lambdabot>Haskell pastebin: http://hpaste.org/new
17:33:47<kpreid>You're not trying to define the data type at the ghci command line, are you?
17:33:54<kpreid>ghci only takes expressions.
17:33:57<JamesSanders>no
17:34:02<kpreid>If that's not the problem, pastebin ^ your code
17:34:15<JamesSanders>when I load the module into ghci I get the error
17:34:23<ski>(also paste the error you get)
17:34:58<JamesSanders>http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5507#a5507
17:35:25<Beelsebob>that's not all the source
17:35:30<Beelsebob>nor the error
17:35:45<Saizan>well it's enough source
17:35:51<JamesSanders>http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5508#a5508
17:35:54<JamesSanders>that is the error
17:36:04<Saizan>JamesSanders: you've to put parentheses around ("htest")::PrivateName
17:36:12<mauke>("htest" :: PrivateName)
17:36:20<Saizan>otherwise it parses what comes after as part of the type
17:36:24<ski>(JamesSanders : next time, annotate the same paste with related pastes :)
17:36:25<mauke>("test") is the same as "test"
17:36:25<Beelsebob>oh, heh, well spotted Saizan
17:36:39<JamesSanders>sorry
17:37:55<kpreid>JamesSanders: Similar problem in 'main' -- you're saying that join "test" is of type Group a
17:38:12<kpreid>well, I suppose it is if Group is a type alias for IO
17:38:21<kpreid>but I suspect you meant ("test" :: Group a)
17:38:32<kpreid>use spacing. :: is least-precedence, not highest
17:39:30<JamesSanders>so I went ahead and removed main
17:39:40<Saizan>you actually have to use mkGroup to get a Group
17:39:58<Saizan>(that part of the api is a bit annoying maybe)
17:40:33<JamesSanders>ah seems like I might need to read up a little more on hspread
17:41:02<Saizan>i'm the author, so you can blame me for the lack of documentation :)
17:41:56<karld>I'm a newbie. Is there a way to apply something like ( take 2 ) to a list until there are no elements remaining and return a list of lists?
17:42:27<mauke>> iterate (take 2) "foo bar"
17:42:28<lambdabot> ["foo bar","fo","fo","fo","fo","fo","fo","fo","fo","fo","fo","fo","fo","fo"...
17:42:33<mauke>no!
17:42:38<karld>iterate!
17:42:41<karld>thanks
17:42:45<mauke>> iterate (drop 2) "foo bar"
17:42:46<lambdabot> ["foo bar","o bar","bar","r","","","","","","","","","","","","","","","","...
17:42:56<Saizan>> map (take 2) . iterate (drop 2) $ [1..10]
17:42:57<lambdabot> [[1,2],[3,4],[5,6],[7,8],[9,10],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[...
17:43:01<JamesSanders>Saizan: small world
17:43:03<mauke>> takeWhile (not . null) . iterate (drop 2) $ "foo bar"
17:43:04<lambdabot> ["foo bar","o bar","bar","r"]
17:43:34<karld>Cool, thanks for all the answers
17:43:38<ski>> unfoldr (\as -> guard (not (null as)) >> return (splitAt 3 as)) "foo bar baz"
17:43:39<lambdabot> ["foo"," ba","r b","az"]
17:44:01<ski>> unfoldr (\as -> if null as then Nothing else Just (splitAt 3 as)) "foo bar baz" -- if you prefer
17:44:02<lambdabot> ["foo"," ba","r b","az"]
17:45:16<rfmge>> replicateM 3 "HT"
17:45:17<lambdabot> ["HHH","HHT","HTH","HTT","THH","THT","TTH","TTT"]
17:45:22<rfmge>can someone explain how 'replicateM n list' generates all permutations of length n of the given list?
17:45:30<lilac>@src replicateM
17:45:30<lambdabot>replicateM n x = sequence (replicate n x)
17:45:50<lilac>rfmge: replicate 3 "HT" returns ["HT", "HT", "HT"]
17:46:00<ski>> unfoldr (\as -> const (splitAt 3 as) `liftM` guard (not (null as))) "foo bar baz" -- hm, longer :)
17:46:01<lambdabot> ["foo"," ba","r b","az"]
17:46:01<lilac>rfmge: sequence for the list monad is nondeterministic choice
17:46:31<rfmge>lilac: okay, that helps
17:46:40<ski>> return (,,) `ap` [0,1] `ap` [2,3] `ap` [4,5]
17:46:41<lambdabot> [(0,2,4),(0,2,5),(0,3,4),(0,3,5),(1,2,4),(1,2,5),(1,3,4),(1,3,5)]
17:47:02<ski>> do x <- [0,1]; y <- [2,3]; z <- [4,5]; return (x,y,z)
17:47:04<lambdabot> [(0,2,4),(0,2,5),(0,3,4),(0,3,5),(1,2,4),(1,2,5),(1,3,4),(1,3,5)]
17:47:16<ski>> [(x,y,z) | x <- [0,1] , y <- [2,3] , z <- [4,5]]
17:47:18<lambdabot> [(0,2,4),(0,2,5),(0,3,4),(0,3,5),(1,2,4),(1,2,5),(1,3,4),(1,3,5)]
17:47:19<lilac>rfmge: sequence is nondeterministic choice because it's the repeated application of >>=, and >>= on lists applies the rhs to every element of the lhs
17:47:49<ski>> liftM3 (,,) [0,1] [2,3] [4,5] -- for completeness, i suppose
17:47:50<lambdabot> [(0,2,4),(0,2,5),(0,3,4),(0,3,5),(1,2,4),(1,2,5),(1,3,4),(1,3,5)]
17:47:53<ski>@src liftM3
17:47:54<lambdabot>liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
17:48:03<rfmge>> "H" >>= "HT"
17:48:04<lambdabot> Couldn't match expected type `GHC.Types.Char -> [b]'
17:48:09<lilac>rfmge: put another way, if you think of [] as the nondeterminism monad, you're asking "give me 3 things taken nondeterministically from ['H', 'T']"
17:48:30<ski>> "ab" >>= \x -> x : "cd"
17:48:31<lambdabot> "acdbcd"
17:48:45<Cale>> replicateM 3 "HT"
17:48:46<lambdabot> ["HHH","HHT","HTH","HTT","THH","THT","TTH","TTT"]
17:48:50<ski>> "ab" >>= \x -> "cd" >>= \y -> [x,y,'*']
17:48:51<lambdabot> "ac*ad*bc*bd*"
17:49:30<lilac>> do x <- "ab"; y <- cd; x:y:"*"
17:49:31<lambdabot> Not in scope: `cd'
17:49:37<lilac>> do x <- "ab"; y <- "cd"; x:y:"*"
17:49:38<trofi>> eval "1+2"
17:49:39<lambdabot> "ac*ad*bc*bd*"
17:49:40<lambdabot> Not in scope: `eval'
17:49:45<wjt>@pl \f x -> fromMaybe x (f x)
17:49:45<lambdabot>ap fromMaybe
17:49:59<ski>@redo "ab" >>= \x -> "cd" >>= \y -> [x,y,'*']
17:49:59<lambdabot>do { x <- "ab"; y <- "cd"; [x, y, '*']}
17:50:01<wjt>is there a better name for that other than ap?
17:50:27<Saizan>the only other name is <*>
17:50:35<Cale>wjt: Oh, what a curious application of ap :)
17:50:35<lesshaste>hi all
17:50:46<ski>@type \f x -> fromMaybe x (f x)
17:50:47<Cale>hello
17:50:47<lambdabot>forall a. (a -> Maybe a) -> a -> a
17:50:52<lilac>rfmge: another way of looking at it is, replicateM n x = do v1 <- x; ...; vn <- x; return [v1,v2,...,vn]
17:50:56<trofi>:t fromMaybe
17:50:57<lambdabot>forall a. a -> Maybe a -> a
17:51:06<wjt>Cale: yeah, it made me smile
17:51:20<wjt>in this case, i want to strip a prefix from a path if it has it, but otherwise leave it intact
17:51:25<rfmge>lilac: okay, it makes more sense now, thanks
17:51:31<ski>\f -> fromMaybe `ap` f
17:51:37<ski>(fromMaybe `ap`)
17:51:38<wjt>so i'm using \p -> fromMaybe p (stripPrefix "foo/bar" p)
17:51:48<^Someone^>lilac: I use Konversation, and it has colored nicks. Interestingly, your nick color is very close to lilac xD
17:51:58<ski>fromMaybe `ap` stripPrefix "foo/bar"
17:52:01<lilac>^Someone^: woo yay :)
17:53:13<^Someone^>lilac: http://imagebin.org/51219
17:53:20<wjt>using the ((->) r) monad makes me a bit sad
17:53:36<wjt>I guess I'm surprised that S isn't sitting around somewhere less obtuse :)
17:53:38<Cale>wjt: I suppose you could use fromMaybe <*> stripPrefix "foo/bar"
17:54:02<Cale>wjt: <*> is in Control.Applicative
17:54:46<Cale>wjt: Though, that's using the ((->) e) Applicative functor instance instead :)
17:54:50<wjt>Cale: well exactly :P
17:55:06<Cale>wjt: The lovely thing about that is that the Applicative methods for ((->) e) are *exactly* K and S.
17:55:12<wjt>i guess i'm golfing here anyway
17:55:28<wjt>Cale: oh, sure
17:55:29<Cale>and the Functor instance has fmap = (.)
17:55:32<lilac>wjt: in that case, use stripPrefix "foo/bar" p <:> p
17:55:52<lilac>ACTION still pimping out <?> and <:>
17:55:56<Cale><:>
17:55:57<Cale>?
17:56:00<wjt>@src (<:>)
17:56:00<lambdabot>Source not found. Maybe you made a typo?
17:56:03<wjt>@ty (<:>)
17:56:04<lambdabot>Not in scope: `<:>'
17:56:11<Cale>ACTION does not know of it
17:56:14<ski>@index <:>
17:56:15<lambdabot>bzzt
17:56:19<lilac><?> :: Bool -> a -> Maybe a; <:> :: Maybe a -> a -> a
17:56:33<Cale>ah
17:56:35<mauke>:t fromMaybe
17:56:36<Cale>cute
17:56:36<lambdabot>forall a. a -> Maybe a -> a
17:56:42<wjt>nice
17:56:43<lilac>ACTION will get around to uploading to hackage Real Soon Now
17:57:36<Cale>I actually rather like how (fromMaybe <*> stripPrefix "foo/bar") reads.
17:57:44<lilac>@let False <?> a = mzero; True <?> a = return a; (<:>) = flip fromMaybe
17:57:46<lambdabot> Defined.
17:57:47<Saizan>why <:> ?
17:57:59<Cale>Saizan: It agrees with C syntax in a funny way
17:58:00<wjt>Saizan: by analogy to ?: in C
17:58:06<hackagebot>bindings-libusb 0.0.3
17:58:10<Saizan>ah, i see
17:58:23<lilac>> map (\a -> (a > 3) <?> a - 3 <:> 0) [1..10]
17:58:24<lambdabot> No instance for (GHC.Num.Num (m a))
17:58:24<lambdabot> arising from the literal `0' at <int...
17:58:35<monochrom>ACTION is eager for Haskell Weekly News
17:58:44<lilac>:(
17:58:50<Cale>ACTION is lazy for Haskell Weekly News
17:59:27<kig>is there an optimized lib for fiddling with 4x4 opengl transformation matrices?
17:59:34<monochrom>ACTION is strict for Haskell Weekly News
17:59:43<ski>> map (\a -> (a > 3) <?> (a - 3) <:> 0) [1..10]
17:59:45<lambdabot> [0,0,0,1,2,3,4,5,6,7]
18:00:07<lament>Haskell Weekly World News?
18:02:17<lilac>> (<:> '?') <$> safeHead <$> ["foo", "bar", "", "baz"]
18:02:19<lambdabot> "fb?b"
18:11:11<hackagebot>bindings-common 0.1.3
18:25:49<olsner>hmm, ghci seem to get the column numbers wrong (one off, presumably from the '>') for literal haskell
18:35:03<JamesSanders>Saizan: join expects a Group but mkGroup gives Maybe(Group), how do I get around that
18:35:24<JamesSanders>sorry talking about hspread btw
18:35:54<Saizan>JamesSanders: you've to pattern match on the returned Maybe
18:36:07<Saizan>JamesSanders: the point is that not all strings are valid group names
18:36:14<JamesSanders>ah
18:36:17<JamesSanders>makes sense
18:36:48<gwern>System.Directory is in directory, which works on windows, right
18:37:09<EvilTerran>gwern, in my experience, yes
18:37:18<gwern>experience? no guarantees?
18:37:36<EvilTerran>i've used it, it worked for me. YMMV.
18:37:56<Saizan>System.Directory is supposed to abstract over the platform, yeah
18:38:17<EvilTerran>i don't know the official status; i've not felt the need to look it up, seeing as it WFM.
18:48:57<voker57_>@hoogle (a, a) -> [a,a]
18:48:57<lambdabot>Parse error:
18:48:57<lambdabot> --count=20 "(a, a) -> [a,a]"
18:48:57<lambdabot> ^
18:50:06<ClaudiusMaximus>is call-by-need an optimal evaluation strategy for untyped lambda calculus? my naive evaluator is very slow (in (\x . f x x) y it ends up evaluating y twice...)
18:51:23<mauke>then it's obviously not optimal
18:51:41<byorgey>ClaudiusMaximus: call-by-need is only efficient if you do some sort of sharing / graph reduction.
18:51:55<ClaudiusMaximus>my naive evaluator isn't call-by-need
18:52:00<Cale>ClaudiusMaximus: You seem to be doing plain outermost-first evaluation
18:52:07<ClaudiusMaximus>Cale: yes indeed
18:52:18<Cale>(I don't understand these call-by-X evaluation strategy names)
18:52:53<ibid>ClaudiusMaximus: call by need is not optimal, if measured by number of beta reductions. see the work of levy et al on optimal beta reduction
18:52:55<Cale>In order to do lazy evaluation, you need to ensure that whenever a function parameter occurs more than once in the body of a function, then any results of evaluating it are shared between the copies.
18:52:59<byorgey>call-by-need = outermost-first
18:53:08<byorgey>call-by-name = that, but with sharing
18:53:19<ibid>byorgey: you have that backward
18:53:25<Cale>byorgey: Yeah, but those names are very unintuitive to me.
18:53:26<byorgey>oh, do I?
18:53:30<byorgey>Cale: me too.
18:53:40<byorgey>well, and apparently I had them backwards. =)
18:53:42<mornfall>call-by-{need,name} is stupid :)
18:53:46<ibid>yes, call-by-name is weak normal order reduction
18:53:55<Cale>I don't see why people don't just say what they mean :)
18:53:57<ibid>call by need is that + sharing
18:54:01<mornfall>call-by-value and call-by-reference make some limited sense I guess :)
18:54:15<ibid>call by name goes back to Algol 60
18:54:31<mornfall>Yes, and it was really by name then, IIRC.
18:54:38<ibid>and call by need is iirc almost as old as wadsworth's thesis
18:55:51<ibid>(the name, i mean)
18:55:59<Cale>Even for call-by-value, it makes more sense to me just to say 'innermost-first'
18:56:14<ibid>ah, but call by value is *not* innermost first
18:56:21<mornfall>Lol. :)
18:56:21<ibid>call by value is the weak version of that
18:56:33<ibid>(ie. never reduce under a lambda)
18:56:59<mornfall>call by value = strict, call by *cough* name = normal, call by need = lazy? : - )
18:57:23<ibid>mornfall: call by name is weak normal, otherwise correct
18:57:43<Cale>Ah, well then, it's still clearer to say weak innermost-first or innermost-first without evaluating under lambdas.
18:58:03<mornfall>So what's the weakness about, then?
18:58:20<Cale>mornfall: Whether the evaluator will evaluate inside of an unapplied lambda
18:59:03<ibid>and basically no evaluator that is intended for programming does that
18:59:26<mornfall>http://en.wikipedia.org/wiki/Evaluation_strategy has all of it :)
18:59:31<Cale>Yeah, when I say 'innermost first' I usually mean 'without evaluating under lambda'
18:59:31<ibid>(evaluators that are inside theorem provers or partial-evaluation optimizers do)
18:59:44<marcot>Why aren't more licenses add to the list in Distribution.License?
18:59:44<lambdabot>marcot: You have 1 new message. '/msg lambdabot @messages' to read it.
19:00:11<marcot>http://www.opensource.org/licenses/category
19:00:14<ibid>lambdabot: why do you insist on that broken message interface, when Freenode provides a better one?
19:00:16<Cale>I think it's probably more sensible to adopt a convention of calling the versions which do evaluate underneath lambdas 'strong'
19:00:17<marcot> .:: Licenses that are popular and widely used or with strong communities ::.
19:00:35<ibid>Cale: people do that, when it is important, yes :)
19:04:46<ClaudiusMaximus>so for sharing i guess i need something like data Term = Variable Name | Lambda Name Term | Apply Term Term | Reference Integer along with type Graph = Map Integer Term
19:06:42<marcot>I'm trying to use UnkownLicense in the license field of a cabal file, but I'm getting: Setup: questionary.cabal:5: Parse of field 'license' failed.
19:08:33<MyCatVerbs>marcot: spelling error? It's UnknownLicense.
19:09:38<marcot>MyCatVerbs: no, this was only to type here on IRC.
19:09:45<marcot>I tried here:
19:09:55<marcot>> read "UnknownLicense \"FreeBSD\"" :: License
19:09:56<lambdabot> Not in scope: type constructor or class `License'
19:10:01<mmorrow>what is the reverse postorder of the graph [(0,[1,2]),(1,[0,2]),(2,[])] ?
19:10:04<marcot>And it worked in ghci.
19:10:13<mmorrow> [0,1,2], right?
19:10:45<MyCatVerbs>marcot: er... why specify the license as unknown "FreeBSD"?
19:10:49<mmorrow>suprisingly there are no examples to verify on google...
19:11:02<marcot>MyCatVerbs: can you configure a cabal package with this field there? I'm using ghc 6.10.3, and cabal 1.6.0.3
19:11:18<MyCatVerbs>There are BSD-2, BSD-3 and BSD-4 entries for the license, and people will be much happier if you write one of those in.
19:11:40<marcot>MyCatVerbs: There's not BSD-2.
19:11:55<marcot>MyCatVerbs: If there was, I think it would mean the same license as FreeBSD.
19:12:12<MyCatVerbs>Eh, just make it BSD-3. BSD-2 and BSD-3 aren't, AIUI, interestingly different.
19:12:53<marcot>http://www.gnu.org/licenses/license-list.html#FreeBSD
19:14:20<marcot>3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
19:14:23<marcot>This is the difference.
19:14:38<marcot>And I don't want to have this clause in my license. So, it's not BSD3.
19:14:57<roconnor>ACTION uses MIT
19:15:11<marcot>MIT is also cool.
19:15:21<marcot>roconnor: do you use BSD3 in .cabal?
19:15:41<fracture>I am trying to import Control.Monad.Reader, and get
19:15:42<fracture> Failed to load interface for `Control.Monad.Reader':
19:15:42<fracture> it was found in multiple packages: monads-fd-0.0.0.1 mtl-1.1.0.2
19:15:44<roconnor>no
19:15:47<fracture>(in ghc)
19:15:55<fracture>anyone know what I need to do?
19:15:56<roconnor>I use unknown licence
19:16:11<MyCatVerbs>fracture: ghc-pkg hide monads-fd # at the command prompt, should solve this.
19:16:18<marcot>roconnor: UnknownLicense or OtherLicense? I can't make UnknownLicense work here..
19:16:40<MyCatVerbs>What the Hell is monads-fd anyway? People really should not be writing packages that conflict with mtl!
19:16:44<roconnor>sorry OtherLicense
19:16:45<seliopou>fracture, or you can use ghc's -hide-package flag
19:16:50<fracture>dunno
19:16:53<fracture>ok thanks
19:16:55<marcot>Has anyone ever used UnknownLicense?
19:16:56<fracture>I dunno what monads-fd is
19:17:04<seliopou>it's mtl with functional dependencies
19:17:11<seliopou>instead of type classes
19:17:15<fracture>I think the only package I've installed that is not default was a Data.Numbers thing
19:17:21<fracture>(prime number functions)
19:17:28<roconnor>marcot: conal was trying a few days ago, and failing IIRC
19:17:41<marcot>roconnor: hum, good to know I'm not the only one.
19:18:12<MyCatVerbs>fracture: cabal install chases dependencies. So if Data.Numbers requires monads-fd then it'll install both.
19:18:20<fracture>*nod*
19:23:31<marcot>roconnor: They've added MIT in darcs version of cabal.
19:24:45<roconnor>marcot: yes
19:25:59<thoughtpolice>well, the idea is that cabal is smart enough to do the hard stuff providing you write your dependencies correctly
19:26:05<thoughtpolice>but shadowing names is never a good idea, no
19:26:36<thoughtpolice>it makes it particularly problematic for GHC just on the command line (since you have to -hide-package) unless you use the PackageImports extension, which helps
19:27:02<thoughtpolice>but it's still not very fun to deal with
19:27:15<thoughtpolice>mtl may be on the way out anyway
19:27:24<thoughtpolice>providing we can get some sort of consensus to switch
19:28:16<thoughtpolice>I do *not* like how monads-fd and monads-tf etc. shadow the mtl names, however.
19:28:37<thoughtpolice>i should probably just use monadLib or something
19:29:19<roconnor>> sqrt (1-0.568)
19:29:21<lambdabot> 0.6572670690061994
19:29:43<roconnor>thoughtpolice: they are supposed to be drop in replacements for the mtl
19:30:18<roconnor>> 1-sqrt (1-0.568)
19:30:18<lambdabot> 0.34273293099380064
19:31:18<thoughtpolice>roconnor: can packages which work with mtl work without problem using e.g.transformers+monads-fd as a drop-in?
19:31:50<sjanssen>thoughtpolice: I believe you have to add extra imports to get the classes
19:32:41<thoughtpolice>the problem is that I have packages which I use, some of which use mtl, some of which use transformers+something, and it makes it annoying to test things with ghci sometimes
19:33:36<thoughtpolice>if we see a shift hopefully it will be soon, so I can cabal uninstall mtl and not have that problem anymore
19:33:55<roconnor>thoughtpolice: *shrugs* that's what you get for using a global environment for ghc packages.
19:34:10<Berengal>thoughtpolice: If you're only troubled in ghci, you can use :set -hide-package to hide one of them
19:34:38<thoughtpolice>Berengal: I can totally get around it (PackageImports works good,) I just don't like it. :)
19:36:39<thoughtpolice>sjanssen: really? awesome. that makes switching simple, worthy of automating, even if that's all it takes.
19:38:35<roconnor>thoughtpolice: switch to monadLib instead
19:39:26<thoughtpolice>roconnor: I like monadLib a lot (and use it,) I just want a solution for *that* problem. :)
19:39:48<thoughtpolice>although last I remember I had to do something to get it to work with 6.10
19:39:52<thoughtpolice>that was a while ago
20:01:11<MrChutney>I'm trying my hand at a lexical analyzer for this small project of mine. I have a language designed, and I have this datatype which describes a set of instructions.
20:01:45<MrChutney>And I want to make some function, f, which converts from the language to the instructions.
20:01:58<MrChutney>I've considered a certain approach, but I'm not terribly certain of myself:
20:02:32<MrChutney>I'm wanting to create an intermediate language, which is a subset of valid code under the entire language:
20:02:45<MrChutney>And under this subset, all code is unsynonymous
20:03:18<MrChutney>And thus any line of code corresponds uniquely to an instruction in my datatype, so that there is an isomorphism between the two.
20:04:06<MrChutney>The drawback is that this involves a lot of rearranging of code, and since I am trying to make an interpreter with concerns about efficiency, I'm not utterly convinced of my method :/
20:04:51<Saizan>the representation of the syntax tree and the code interpreted by your runtime can be different
20:04:52<MrChutney>Can anyone offer any advice on the subject?
20:05:06<Saizan>i.e. you might have more than one layer
20:05:34<Saizan>that's what's usually done nowadays, afaik
20:06:35<Baughn>MrChutney: Modern "interpreters" typically compile to bytecode, which is then interpreted
20:06:49<Baughn>FWIW, a primitive compiler can be really very simple indeed
20:07:07<MrChutney>I've honestly never heard of syntax trees until now, and this gives me something to work with. Thanks a bunch!
20:08:13<lunarisbluemoon>Hi #haskell; I'm writing up a benchmark in Haskell which is essentially a port of a C program. Any tips for speed?
20:08:28<Saizan>ah, the "abstract syntax tree" is how the result of parsing is generally called
20:09:18<mgee>hi, i am using the HERA package, which provides the datatype CReal. Now ghc tells me that I have to add "(RealFloat CReal) =>" to every function using CReal... how can i prevent this? I just want to use the datatype without any instance declarations...
20:09:23<MrChutney>Oh, I see.
20:09:35<lunarisbluemoon>I've read several articles on the matter, but really I'm not a Haskell guru and am wondering if it's standard practice to use a state monad to mimic an imperative program.
20:09:50<lunarisbluemoon>mgee: what is the exact error message?
20:10:17<Beelsebob>lunarisbluemoon: people seem to do it a lot
20:10:23<Beelsebob>but I would hardly call it natural
20:10:33<Saizan>lunarisbluemoon: direct recursion or the use of combinators like foldl' / foldr are often more natural
20:10:36<Beelsebob>better to find a truely functional description of the problem
20:10:43<mgee>lunarisbluemoon: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2537#a2537
20:10:47<Saizan>it mostly depends on the problem
20:11:32<Saizan>a State monad is most useful to organize a larger program than a little benchmark
20:11:33<lunarisbluemoon>mgee: That's not asking you to add "(RealFloat CReal) => " to every function, is it?
20:11:44<lunarisbluemoon>Saizan: this benchmark isn't that little.
20:11:46<lunarisbluemoon>:)
20:11:50<mgee>lunarisbluemoon: instead?
20:12:15<lunarisbluemoon>mgee: You need something like "instance RealFloat CReal where ..." somewhere don't you?
20:12:30<lunarisbluemoon>I've never used the package, sorry.
20:12:39<lunarisbluemoon>Does it provide both RealFloat and CReal?
20:12:53<Saizan>?src RealFloat
20:12:53<lambdabot>Source not found. The more you drive -- the dumber you get.
20:13:00<mgee>lunarisbluemoon: mhh. it provides fractional. but not realfloat :-/
20:13:54<lunarisbluemoon>Which function do you want?
20:13:55<roconnor>CReal isn't an instance of RealFloat
20:13:56<lunarisbluemoon>floatDigits?
20:14:10<lunarisbluemoon>Isn't CReal for "exact real arithmetic?"
20:14:17<roconnor>oh
20:14:23<roconnor>or is this some other CReal?
20:14:46<lunarisbluemoon>I'm not sure :)
20:14:52<mgee>lunarisbluemoon: yes it is. I want to use /=. This should be covered by Eq. mhh ok I investigate a little bit. thanks
20:15:05<mgee>roconnor: It is exact real arithmetic
20:15:15<lunarisbluemoon>mgee: As you say, shouldn't CReal have an Eq instance?
20:15:15<J11>Is there a monadic operator that works almost like >>= but is m a -> (a -> m b) -> m a ?
20:15:41<mgee>lunarisbluemoon: it has. i am wondering why haskell tells me to add an instance of realfloat just because i am using /=
20:15:50<Baughn>@type (/=)
20:15:52<lambdabot>forall a. (Eq a) => a -> a -> Bool
20:16:04<Baughn>Well, I don't think /= is what is doing it.
20:16:10<lunarisbluemoon>mgee: That may not be it - what are f and g's types in your pasting?
20:16:27<lunarisbluemoon>mgee: Alternatively, do the bodies of f and g reference any of the functions in the RealFloat typeclass?
20:17:16<mgee>lunarisbluemoon: I am not quite sure. Actually I am modifying someone else's work. I think f and g are "((Bool,Bool) -> Complex CReal)"
20:17:17<lunarisbluemoon>J11: Hoogle doesn't think so.
20:17:17<roconnor>mgee: using (/=) doesn't require a RealFloat instance
20:17:34<lunarisbluemoon>J11: At the risk of sounding stupid, what's the second argument's purpose?
20:17:46<lunarisbluemoon>(Since b seems unused?)
20:18:15<lunarisbluemoon>mgee: It's certainly not Eq that's causing this.
20:18:26<roconnor>what a strange error.
20:18:44<lunarisbluemoon>HeHe says :)
20:19:17<roconnor>oh
20:19:23<Zao>J11: const would satisfy your signature, but that's probably not what you intended.
20:19:23<lunarisbluemoon>Sorry, irssi went a bit haywire.
20:19:28<roconnor>Complex is broken
20:19:32<roconnor>and doesn't work with CReal
20:19:55<mgee>roconnor: whaat? oh no
20:19:56<roconnor>some idiot wrote:
20:19:57<roconnor>data (RealFloat a) =>
20:19:59<roconnor> Complex a = !a :+ !a
20:19:59<J11>I don't needs it's output, the function will change a state
20:20:00<roconnor> deriving (Eq,Read,Show)
20:20:03<roconnor>into the standard
20:20:10<roconnor>ACTION glares at Simon
20:20:15<mgee>roconnor: so?
20:20:37<roconnor>the :+ constructor requires that the parameters be RealFloat for no good reason.
20:20:47<roconnor>@type (:+)
20:20:48<lambdabot>forall a. (RealFloat a) => a -> a -> Complex a
20:20:51<mgee>roconnor: oh no
20:20:56<lunarisbluemoon>God bless '98 xD
20:21:16<Saizan>roconnor: it's required for something in the instance of Num, iirc
20:21:25<roconnor>oh?
20:22:10<roconnor>I see
20:22:16<roconnor>That's still stupid
20:22:27<Zao>@type \a f -> a >>= \x -> f x >> pure x
20:22:29<lambdabot>forall (m :: * -> *) a a1. (Applicative m, Monad m) => m a -> (a -> m a1) -> m a
20:22:30<Zao>J11: Like that?
20:22:52<roconnor>mgee: the solution is to write your own Complex module/type
20:22:58<roconnor>mgee: and use that instead
20:23:29<Zao>@type \a f -> do { x <- a ; f x ; pure x }
20:23:31<lambdabot>forall (m :: * -> *) b a. (Monad m, Applicative m) => m b -> (b -> m a) -> m b
20:23:35<Zao>Or if you want to use fancy sugar :)
20:23:55<J11>yes looks like it
20:23:55<mgee>roconnor: I just discovered another CReal: http://darcs.augustsson.net/Darcs/CReal/ (this has an instance Num)
20:24:24<roconnor>mgee: you can probably just copy the Complex module from the report and fix it.
20:24:31<roconnor>mgee: that is the CReal I was thinking of.
20:24:56<mgee>roconnor: first I try to use that other CReal... this way I also get rid of the mpfr dependency
20:25:19<roconnor>oh
20:25:38<roconnor>mgee: right, I think that Augustsson's CReal might have a stupid RealFrac instance.
20:26:17<roconnor>I guess that is another solution, write a RealFrac instance for your CReal. I don't like that idea much myself.
20:26:36<mgee>^^
20:27:24<Geheimdienst>hey guys, i got a newbie question
20:27:34<roconnor>instance RealFloat CReal where
20:27:36<roconnor> floatRadix _ = error "CCeal.floatRadix"
20:27:38<roconnor>...
20:27:40<Geheimdienst>i'm seeing a linker error when compiling
20:28:25<Geheimdienst>about 20 errors like this: t.o: In function `rWb_info':
20:28:26<Geheimdienst>(.text+0xaa): undefined reference to `mtlzm1zi1zi0zi0_ControlziMonadziError_zdf13_closure'
20:28:35<Saizan>Geheimdienst: use --make
20:28:43<Zao>Or -package whatever
20:29:02<Geheimdienst>you mean ghc --make ?
20:29:11<Zao>Or cabal, which concocts a nice command line from the packages listed in the .cabal file.
20:29:11<roconnor>CReal really ought not to be an instance of RealFloat.
20:29:14<Zao>Geheimdienst: YEs.
20:29:25<roconnor>> magnitude (1:+1) :: CReal
20:29:26<lambdabot> 1.4142135623730950488016887242096980785697
20:29:42<Geheimdienst>ok great, that fixed it :-)
20:29:42<roconnor>but it seems to work
20:29:47<Geheimdienst>thanks a ton
20:30:08<lunarisbluemoon>So guys, excuse me asking again - will a state monad cost me a lot of speed?
20:32:50<dons>Haskell Platform testing time: http://projects.haskell.org/pipermail/haskell-platform/2009-June/000411.html
20:32:53<Saizan>lunarisbluemoon: it can cost some speed, yes, a way to make it faster is using the monad-ran package, however it depends on the use-case
20:33:03<dons>If you're on windows: check this installs, and let me no YES/NO: http://code.haskell.org/~refold/HaskellPlatform-2009.2.0.1-rc2-setup.exe
20:33:10<dons>Unix, same story, http://haskell.org/~duncan/haskell-platform-2009.2.0.1.tar.gz
20:33:34<dons>note: the windows installer will install GHC on your system
20:34:10<lunarisbluemoon>Saizan: Thanks; also should I be worried about using mutable arrays (IOArray for example)?
20:35:25<roconnor>lunarisbluemoon: the state monad does exactly the same thing as manually threading the state through your code. It simply provides combinators that make doing so easier.
20:36:00<lunarisbluemoon>roconnor: That makes sense, I'm just worried I'm making stupid errors.
20:36:05<roconnor>lunarisbluemoon: to answer if this is slow, I need to know what this is opposed to doing.
20:36:06<lunarisbluemoon>Since I'm way off getting the C speed.
20:36:32<lunarisbluemoon>roconnor: At the top level it's replacing having globals in C.
20:36:42<lunarisbluemoon>(I never said it was a nice benchmark :)
20:37:00<Saizan>lunarisbluemoon: large mutable arrays have poor GC performance currently
20:37:06<mm_freak>is there any way to easily parse any reasonable date/time string?
20:37:15<mm_freak>no specific format, that is
20:37:18<lunarisbluemoon>Saizan: I see; thanks for your help.
20:37:48<lunarisbluemoon>mm_freak: I only know of the parsedate package; not sure if it does what you want.
20:38:17<lunarisbluemoon>Afaik I think you need to give it a format string though.
20:38:22<lunarisbluemoon>:/
20:38:28<mm_freak>Date.Time.Format has the parseTime function, but it asks for a specific format "with some variations allowed"
20:39:25<paper_cc>mm_freak: well, you won't be able to tell MM/DD/YYYY from DD/MM/YYYY in some cases anyway =)
20:39:48<mm_freak>hmm, then i
20:39:58<mm_freak>hmm, then i'll accept specific formats only =)
20:41:55<roconnor>ISO 8601 FTW!
20:41:58<paper_cc>ACTION lives in Russia and has great trouble understanding US dates formatted as MM/DD
20:42:37<Zao>Big-endian padded dates are nice.
20:42:40<Zao>Sorts well too.
20:43:31<riddochc>Right, so... now that I'm in front of my computer, I can see from ghci what (,) does. It wasn't obvious from when it's first used in the monads chapter of real world haskell.
20:44:21<riddochc>I'm running into a surprisingly large number of things in the real world haskell book, showing up in the code but never get explained.
20:46:28<riddochc>In the logger example, for the regexes, I can't find any definition for the execLogger aka runLogger function.
20:46:28<paper_cc>@where LYAH
20:46:28<lambdabot>www.learnyouahaskell.com
20:46:45<paper_cc>@ty runWriter
20:46:46<lambdabot>forall w a. Writer w a -> (a, w)
20:47:04<paper_cc>riddochc: Logger is a Writerish thing?
20:48:58<riddochc>paper_cc: It says it's a "specialized version of the standard Writer monad" but it doesn't elaborate on that for another 50 pages, and I haven't gotten that far yet.
20:49:18<paper_cc>@where RWH
20:49:18<lambdabot>is http://www.realworldhaskell.org/blog/
20:50:39<riddochc>paper_cc: Yeah, I haven't looked at what's on the site very carefully, I'm working through the dead-tree version from the library.
20:52:57<mgee>Ok now I got it nearly working! Just one thing missing. CReal is missing the Random instance. So I wanted to add one and let is just wrap around the Double Random instance. I use this code: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2538#a2538
20:53:00<paper_cc>the @where was for me =)
20:53:01<paper_cc>riddochc: the logger example starts with "We'll intentionally keep the internals of the Logger module abstract." and section title "Information hiding"
20:53:04<mgee>the error is also in the paste
20:53:32<mgee>I know that the right side will evaluate to a double value. but if i use read $ random ... I get errors tooo... :( so,ebopdy know why?
20:54:09<paper_cc>@ty randomR
20:54:10<lambdabot>forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
20:54:29<mgee>Here is the paste with the read $ and the new errors: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2539#a2539
20:54:42<riddochc>Hmm. Seems several other people had the same confusion I have - see comments on first paragraph of "Using a new monad: show your work!"
20:54:52<paper_cc>@instances RandomGen
20:54:53<lambdabot>Couldn't find class `RandomGen'. Try @instances-importing
20:55:15<Saizan>?type random
20:55:16<lambdabot>forall g a. (Random a, RandomGen g) => g -> (a, g)
20:55:34<Saizan>mgee: ^^^ the argument is the generator
20:55:47<mgee>ah oh
20:55:52<paper_cc>mgee: well, Double is not an instance of RandomGen
20:55:57<Saizan>mgee: not of the type of value you want to generate
20:56:03<paper_cc>@instances-importing System.Random RandomGen
20:56:04<lambdabot>StdGen
20:56:30<mgee>paper_cc: mhh... so how would i wrap my instance around the random instance of double?
20:56:37<Saizan>so you need something like random g = let (d,g') = random g in (read $ show d,g')
20:56:55<sjanssen>Saizan: or just fromRational?
20:56:56<mgee>Saizan: ah ok. I will try
20:57:05<paper_cc>sjanssen: or realToFrac?
20:57:12<Saizan>sjanssen: yeah, i was going to suggesting some other conversion
20:57:19<sjanssen>paper_cc: yeah, that's the one I meant
20:57:24<Saizan>but i'm not sure what works for Double -> CReadl
20:57:50<Saizan>*CReal
20:58:12<refold> /quit
20:58:12<sjanssen>> realToFrac (1 :: Double) :: CReal
20:58:13<lambdabot> 1.0
20:59:53<riddochc>Hey, cool! My 2:00 AM idea has actually already been looked into - I had the idea that doing things with monads is like working with variations on progn in lisp.
20:59:54<fynn>Hey.
20:59:55<fynn>What's the equivalent of optparse for Haskell?
21:00:33<fynn>(A library like Python's optparse, for parsing command-line arguments)
21:01:38<trofi>@hoogle getOpt
21:01:39<lambdabot>System.Console.GetOpt getOpt :: ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
21:01:39<lambdabot>module System.Console.GetOpt
21:01:39<lambdabot>System.Console.GetOpt getOpt' :: ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String], [String])
21:01:41<kynky>ts a string, just parse it ?
21:02:11<paper_cc>@hackage parseargs
21:02:11<lambdabot>http://hackage.haskell.org/cgi-bin/hackage-scripts/package/parseargs
21:02:14<JamesSanders>Saizan: any good (src code) examples of hspread in use
21:03:56<fynn>trofi: so, System.Console.GetOpt should actually be in any 98-compliant Haskell implementation?
21:04:32<trofi>ACTION googles getopt page to read portability section
21:04:40<paper_cc>s/98-compliant/H'98-with-hierachical-modules-compliant/ at lease
21:04:43<paper_cc>*at least
21:05:09<trofi>Portability portable
21:05:09<trofi>Stability experimental
21:05:29<trofi>http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-Console-GetOpt.html
21:06:00<hackagebot>BoundedChan 1.0.0.2
21:06:13<paper_cc>cabal-install and darcs use their own custom parsers anyway
21:06:26<mgee>Saizan: that works nearly... http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2539#a2540 sorry it seems like I am a bit slow today. I tried adding ::Double and ::CReal in some places but it didn't help
21:06:49<trofi>GetOpt.hs does not have any special exts
21:07:51<gwern>trofi: I suspect the stability is experimental because getopt is fairly hard to figure out
21:08:08<mgee>Saizan: i solved it :)
21:08:14<gwern>I had a dickens of a time working getopt out when I was trying to add real options to mueval
21:08:26<idnar>getopt is bad enough in C, why would you inflict it on yourself in Haskell?
21:08:40<Igloo>idnar: What would you recommend instead?
21:08:48<tibbe>is it possible import macros using hsc2hs?
21:08:51<gwern>Igloo: ad hoc parsing using drop and take!
21:08:58<BONUS>what's that library that draws data structures
21:09:01<BONUS>how they point to each other etc
21:09:08<gwern>BONUS: graphvzi
21:09:09<fynn>trofi: thanks.
21:09:11<gwern>*viz
21:09:16<fynn>paper_cc: you too.
21:09:18<idnar>Igloo: I'm not exactly an expert on Haskell command line parsing libraries :/
21:09:21<trofi>gwern: heh, true. i used C' getopt, then ruby's and then haskell's. it was not so intuitive w/o reading docs :]
21:09:23<BONUS>i mean like the one where you pass it [1,2,3]
21:09:30<kau>hello all! how to display a counter that increment itself every seconds (using the State monad)?
21:09:31<BONUS>and it draws the cons' and stuff
21:09:34<Igloo>BONUS: vacuum
21:09:39<BONUS>ah vacuum, yeah
21:09:49<gwern>oh, you meant live haskell datastructures
21:10:02<paper_cc>BONUS: it's actually vacuum-graphviz || vacuum-ubigraph
21:10:03<fynn>gwern, Igloo, idnar: so the general consensus is, it's getOpt or nothing?
21:10:03<gwern>(graphviz can draw data structures. graphs, specifically)
21:10:08<fynn>ACTION misses Python :(
21:10:15<gwern>fynn: well, there are a few obscure other approachs
21:10:19<BONUS>ah :)
21:10:22<gwern>fynn: but who knows what other packages lurk on hackage!
21:10:23<kau>i can't figure it out with State
21:10:31<paper_cc>fynn: there's something called parseargs on hackage
21:10:43<fynn>gwern: there's this other one (yeah, parseargs) but it's self-designated Alpha
21:10:50<Igloo>fynn: getOpt is the best solution I know of
21:11:12<fynn>Igloo: cool. who knows, maybe we'll write an optparse port ourselves
21:11:35<fynn>we're going to be possibly the first commercial entity to release open source Haskell libraries... exciting
21:11:49<gwern>fynn: may not mean much. secretly, haskellers believe a package is only out of alpha/beta when the code is written in coq and compiled to haskell, and has been firetested by the nsa
21:12:00<gwern>fynn: sorry, but galois at least beat you to the punch by years
21:12:18<fynn>gwern: well, 2nd place is pretty good too ;)
21:12:31<gwern>ACTION stares at shoes. no, not there either
21:12:40<kau>nobody has got an idea for my problem?
21:13:06<paper_cc>kau: you can't do that
21:13:21<gwern>kau: where would the state monad get 'seconds' from?
21:13:21<kau>yes we can!
21:13:31<fynn>gwern: we're getting this guy to work in Haskell sort of full time. I'm a bit concerned that there's no large, open-source Haskell codebases out there that commercial entities depend on
21:13:54<fynn>I hope we won't discover down the road that it's because there are huge problems we can't foresee right now.
21:14:02<gwern>fynn: I'd say that just about every commercial entity depending on haskell also depends on that large open-source codebase we call ghc
21:14:22<fracture>is wxHaskell supposed to be good enough for real use? (it's randomly crashing and sometimes giving error dialog boxes about loading comctrl32.dll for me)
21:14:24<fynn>well, the thing is there's no visibility to those applications.
21:14:52<kau>gwern: there is threadDelay?
21:15:00<gwern>kau: but that's up in the IO monad
21:15:00<fynn>gwern: like, in Python, everything depends on CPython, so I can go "yeah, Google Groups and YouTube and a million Django websites are fire-testing CPython daily"
21:15:14<Hunner>If I have a (String -> IO ()) and I want to apply it to a [String], what am I looking for?
21:15:14<riddochc>Is there a good list of larger apps written in Haskell?
21:15:41<gwern>fynn: galois does high-performance, high security programs & libraries for government etc. and dons who works there tells me they're happy with ghc
21:15:45<fynn>with Haskell it's "there are rumored to be some super-secret Haskell stuff done by Galois for the nsa or something, but you need top-secret clearance to even know about it"
21:15:45<Zao>@src mapM_
21:15:47<lambdabot>mapM_ f as = sequence_ (map f as)
21:15:51<Zao>@type mapM_
21:15:53<lambdabot>forall a (m :: * -> *) b. (Monad m) => (a -> m b) -> [a] -> m ()
21:15:55<gwern>Hunner: mapM
21:15:59<Hunner>thanks
21:16:07<kau>i would like my program to just output the number of seconds since it started, never ending...
21:16:17<Zao>As your function yields IO (), you probably don't care about the result, so mapM_
21:16:21<roconnor>Hunner: mapM_
21:16:22<Zao>mapM is when you want a list of the results.
21:16:23<travisbrady>fynn: did you see "Commercial Uses: Going functional on exotic
21:16:23<travisbrady>trades
21:16:27<gwern>fynn: nah, they're released stuff like cryptol which are pretty darn big
21:16:29<travisbrady>woops
21:16:32<Hunner>Yeah, saw that difference. Thanks guys
21:16:42<fynn>travisbrady: nope
21:16:47<paper_cc>kau: when you have time, it's either IO or FRP. State is pure so you can't use it
21:16:47<gwern>fynn: and travisbrady is linking you to a paper whose compiler/dsl was about 30k lines iirc
21:16:59<kau>gwern: oh
21:17:01<travisbrady>fynn: http://www.google.com/url?sa=t&source=web&ct=res&cd=3&url=http%3A%2F%2Fwww.lexifi.com%2Fdownloads%2Ffrankau.pdf&ei=wpYlSrzWI6eWswOxmozIBg&usg=AFQjCNGTOcU4y7JhznjELS76oxBpn9dweg&sig2=iR9U9TP98Zq7BATc1_ZD3Q
21:17:13<Hunner>ACTION wonders why mapM_ is the name of the function and not mapM'
21:17:24<travisbrady>ugh, woops again: www.lexifi.com/downloads/frankau.pdf
21:17:30<Raevel>@hoogle mapM
21:17:30<lambdabot>Prelude mapM :: Monad m => (a -> m b) -> [a] -> m [b]
21:17:30<lambdabot>Control.Monad mapM :: Monad m => (a -> m b) -> [a] -> m [b]
21:17:30<lambdabot>Data.Traversable mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
21:17:33<Zao>Hunner: It owes it to sequence_. Now where that got the underscore from...
21:17:43<gwern>kau: if you just want that, then your program will look something like 'main = main' 0; main' x = print x >> main' (x+1)'
21:17:43<paper_cc>@ty sequence'
21:17:44<lambdabot>Not in scope: `sequence''
21:17:46<Botje>Hunner: maybe because it resembles _ in pattern matching?
21:17:50<Raevel>oh i can't read
21:17:58<Zao>Hunner: Probably related to how you use _ to skip binding pattern matches.
21:18:21<gwern>kau: and if you want every second, it'd be like 'threadDelay 1000 >> print x >> main' (x+1)', if you follow
21:18:31<kau>gwern: OK super
21:18:43<fynn>travisbrady: cool, thanks
21:18:43<Zao>> let f _ _ = "lol" in f 42 3
21:18:45<lambdabot> "lol"
21:18:56<gwern>I can never remember, is it threadDelay 100 that is a second, or threadDelay 1000...
21:19:01<fynn>gwern: we're still sort of pioneering here. well, I guess it's also exciting.
21:19:05<jmcarthur_work>1000000
21:19:07<Berengal>gwern: 10^6
21:19:09<kau>gwern: can i use map to remove the recursion?
21:19:51<eu-prleu-peupeu>hello
21:19:58<O_4>kau: why would you want to?
21:20:00<gwern>kau: not really. you're thinking something like 'main = map (\x -> threadDelay 1000 >> print x) [1..]', right?
21:20:18<paper_cc>@ty repeat
21:20:19<kau>gwern: exactly
21:20:19<lambdabot>forall a. a -> [a]
21:20:21<gwern>kau: but there's no guarantee that this will perform the way you think it will
21:20:24<Zao>@type sequence_ $ repeat $ threadDelay 1000
21:20:26<lambdabot>Not in scope: `threadDelay'
21:20:29<Zao>@type sequence_ $ repeat $ ?threadDelay 1000
21:20:31<lambdabot>forall (m :: * -> *) a t. (Monad m, ?threadDelay::t -> m a, Num t) => m ()
21:20:47<gwern>kau: in theory, ghc could make it so that 1000 of those maps happen simultaneously. that's allowed
21:21:02<paper_cc>gwern: sequence_ $ zipWith (>>) (threadDelay 1000000) (map print [1..]) -- won't this work?
21:21:18<kau>gwern: oh, i guess some sort of strictness is needed here?
21:21:22<Zao>gwern: Which would be harmless as threadDelay is an IO action, and all yours does is generate a list of actions.
21:21:24<gwern>paper_cc: I don't know enough about sequence to say
21:21:31<paper_cc>@src sequence
21:21:32<lambdabot>sequence [] = return []
21:21:32<lambdabot>sequence (x:xs) = do v <- x; vs <- sequence xs; return (v:vs)
21:21:32<lambdabot>--OR
21:21:32<lambdabot>sequence xs = foldr (liftM2 (:)) (return []) xs
21:21:35<roconnor>paper_cc: I don't think that typechecks
21:21:52<paper_cc>@ty threadDelay 1
21:21:53<lambdabot>Not in scope: `threadDelay'
21:22:00<Zao>paper_cc: Control.Concurrent
21:22:02<Berengal>@type let threadDelay :: Int -> IO (); threadDelay = undefined in mapM_ (\x -> threadDelay 1000 >> print x) [1..]
21:22:04<lambdabot>IO ()
21:22:39<paper_cc>@type let threadDelay :: Int -> IO (); threadDelay = undefined in zipWith (>>) (threadDelay 1) (map print [1..])
21:22:40<lambdabot> Couldn't match expected type `[m a]' against inferred type `IO ()'
21:22:40<lambdabot> In the second argument of `zipWith', namely `(threadDelay 1)'
21:22:40<lambdabot> In the expression:
21:22:50<gwern>now, a fold might work
21:22:52<paper_cc>oh
21:22:55<Berengal>@src sequence_
21:22:56<lambdabot>sequence_ ms = foldr (>>) (return ()) ms
21:23:02<gwern>oh :)
21:23:12<jmcarthur_work>heh
21:23:14<Berengal>@src sequence
21:23:14<lambdabot>sequence [] = return []
21:23:14<lambdabot>sequence (x:xs) = do v <- x; vs <- sequence xs; return (v:vs)
21:23:14<lambdabot>--OR
21:23:14<lambdabot>sequence xs = foldr (liftM2 (:)) (return []) xs
21:23:26<mgee>Is it in Haskell impossible to use a Complex Number with arbitrary precision? I think so because the Complex Type requires the RealFloat instance. And this instance want decodeFloat and encodeFloat, which is not possible for a real with arbitrary precision, right?
21:23:46<rubendv>paper_cc: do a repeat on the threadDelay
21:23:52<paper_cc>roconnor: it should be (repeat $ threadDelay 1000000), sorry
21:23:52<Berengal>mgee: Write your own Complex type
21:23:54<gnuvince_>@index comparing
21:23:55<lambdabot>bzzt
21:23:55<rubendv>zipWith needs two lists
21:23:57<roconnor>mgee: unless you give make a "fake" RealFloat instance, yes
21:24:10<ray>encodeFloat = error "floats suck"
21:24:29<roconnor>mgee: this is what numbers package does.
21:24:32<mgee>yeah then my programm terminates
21:24:37<jmcarthur_work>:t (1 :: CReal) :+ 2
21:24:39<lambdabot>Complex CReal
21:25:05<fynn>paper_cc: what does "with compliant hierarchal modules" mean? what kind of a standard is that?
21:25:10<paper_cc>@ty let threadDelay = undefined :: Int -> IO (); print = undefined :: (Show a) => a -> IO () in sequence_ $ zipWith (>>) (repeat $ threadDelay 1) (map print [1..])
21:25:12<lambdabot>IO ()
21:25:13<mgee>Mhh so I have to find the function which is causing the encodeFloat to be called, right?
21:25:19<roconnor> decodeFloat _ = error "CReal.decodeFloat"
21:25:21<roconnor> encodeFloat _ _ = error "CReal.encodeFloat"
21:25:27<kau>sequence $ map (\x -> threadDelay 1000000 >> print x) [1..] works fine!!
21:25:32<roconnor>this is how numbers defines those functions for CReal.
21:26:03<gwern>fynn: it means that one could do 'import Data.List' instead of 'import List'
21:26:12<Berengal>kau: 'seuqence . map' is called mapM, and 'sequence_ . map' is called mapM_, just FYI
21:26:22<gwern>fynn: otherwise you basically have a flat module hierarchy - no nesting
21:26:24<roconnor>mgee: Complex uses magnitude which uses scaleFloat and exponent for precision.
21:26:28<paper_cc>fynn: the hierachical modules addendum (IO -> System.IO, Random -> System.Random etc)
21:26:30<roconnor>@src magnitude
21:26:30<lambdabot>Source not found. Maybe if you used more than just two fingers...
21:26:39<kau>Berengal: tks
21:26:42<roconnor>@type magnitude
21:26:44<lambdabot>forall a. (RealFloat a) => Complex a -> a
21:26:44<gwern>fynn: the hierarchical module is an addition to the haskell '98 standard
21:26:44<Berengal>kau: Also note that it will never return, so using 'sequence' over 'sequence_' is a space leak
21:26:47<mgee>roconnor: ah ok. I saw some code piece which used magnitude
21:26:50<roconnor>src is so random
21:27:02<mgee>roconnor: thanks
21:28:08<kau>i first asked this question to me reading the State monad chapter from RWH
21:28:09<fynn>gwern, paper_cc: OK, so the 3 levels of standards are: 1) Core '98, 2) standard additions to the '98 standard (where are those defined?), 3) platform-specific extensions, defined ad-hoc by the extender (I understand GHC has a ton of those)
21:28:18<kau>indeed i understood quite nothing
21:28:48<kau>is this example re-writable with State?
21:28:55<paper_cc>fynn: really I'm not much into this, but at least there are 1) the FFI addendum and 2) the hierachical modules addendum
21:29:02<paper_cc>kau: no
21:29:03<gwern>fynn: I'd add the common subset of platform-specific extensions between ghc/hugs/yhc as 3.5
21:29:11<gwern>CPP, for example. I think everyone has CPP
21:29:25<paper_cc>kau: time is an impure thing
21:29:39<kau>but State is monadic!
21:29:50<paper_cc>kau: Maybe is monadic too
21:29:54<kau>i figured out that monads where for impure things ;)
21:30:02<paper_cc>kau: nope
21:30:11<gwern>kau: monads are mu!
21:30:19<kau>a state is impure?
21:30:29<paper_cc>kau: State, Writer, Reader, Maybe are perferctly pure
21:30:31<Cale>kau: That's only part of what they're good for.
21:30:36<gwern>do not ask what monads are; let monads ask what you are
21:30:37<kau>yes
21:30:42<Cale>heh
21:30:44<gnuvince_>Is it normal that with a very large list (235,000 words) the following code overflows the stack: maximumBy (comparing length) myWords
21:30:53<gnuvince_>(unless I compile with -O2)
21:30:58<Cale>gnuvince_: yeah
21:30:58<ray>do not use monads, use haskell
21:31:08<gwern>realize the truth: there is no monad.
21:31:16<paper_cc>kau: a state emulates a mutable state, but there's no mutability inside it
21:31:19<ray>there is only Monad
21:31:20<Heffalump>@src maximumBy
21:31:21<lambdabot>Source not found. That's something I cannot allow to happen.
21:31:27<Heffalump>@src Data.List.maximumBy
21:31:27<lambdabot>Source not found. Have you considered trying to match wits with a rutabaga?
21:31:34<mux>monads hide side effects under the carpet.
21:31:37<paper_cc>kau: s/a state/the State/
21:31:40<gnuvince_>Cale: to much thunking?
21:31:43<gnuvince_>*too
21:32:03<Heffalump>it's a foldl, is the problem
21:32:04<Cale>gnuvince_: The problem is that without optimisations, strictness analysis isn't done, and a large expression is constructed consisting of all the elements of the list combined with a max-type function.
21:32:07<Heffalump>so not designed for lazy things like that
21:32:30<paper_cc>kau: State s a is just a fancy way to write a function s -> (s, a) which is perfectly pure
21:32:36<Cale>gnuvince_: Finding a reducible subexpression in that is what causes the stack to overflow.
21:32:46<kau>imaging you receive input from time to time from the user, and you have to compare each inputs to others, would you use State?
21:32:48<Heffalump>why is sum a foldl?
21:33:02<Cale>There really ought to be a sum'
21:33:11<Cale>and a maximumBy' and all those.
21:33:38<conal>time needn't be modeled impurely.
21:33:38<Cale>Though, strictness analysis is good enough now that it usually finds this sort of thing.
21:33:41<Zao>let maximumBy' = tickify maximumBy
21:33:59<Zao>The implementation of tickify is left as an exercise for the reader.
21:34:10<ray>compiler magic
21:35:59<paper_cc>conal: well, is there a way to access time other than doing some IO?
21:36:09<kau>the State monad is a mystery for me ;)
21:37:17<gwern>ACTION has a sudden vision of 50 years from now. people will be writing webpages like 'The Road to FRP', and creating motivational posters of conal which read 'programming: ur doing it rong', and the mainstreamers will be looking up from their GADT design patterns and deriding those FRPers
21:37:33<roconnor>@src State
21:37:34<lambdabot>Source not found. Just try something else.
21:37:35<Berengal>kau: The State monad is just regular code, except it carries one extra value around for you behind the scenes. You can read this value as you wish, and exchange it for a new value in the remaining computation
21:38:18<gwern>@quote state
21:38:18<lambdabot>state says: ?. ++ . read . show . state ?. ++ . read . show . state
21:38:24<kau>Berengal: i see
21:38:29<gwern>@quote state
21:38:29<lambdabot>state says: ?. ++ . read . show . state ?. ++ . read . show . state
21:38:33<conal>gwern: :)
21:38:45<gwern>I'm tempted to delete that quote because it makes no sense whatsoever
21:38:54<gwern>@hoogle (?.)
21:38:54<lambdabot>No results found
21:39:20<roconnor>kau: the state monad just offers a better way of writing f s x = y where {(s1,y1) = foo s x; (s2,y2) = bar s1 y1; (s3,y3) = baz s2 y2; (s4,y) = quux s3 y3}
21:39:41<conal>paper_cc: yeah. check out frp.
21:40:16<paper_cc>conal: well, the interface is pure, but there's still IO under the hood
21:40:34<Heffalump>paper_cc: that's true of any Haskell code
21:40:40<conal>paper_cc: there's IO under the hood of 2+3
21:40:45<Heffalump>it's just hidden by the compiler rather than by unsafePerformIO
21:40:49<kau>ok, then there is no possibility to hold a state through time (during a certain amout of time)?
21:41:16<roconnor>kau: time is not really relvent to state.
21:41:24<Berengal>kau: Not with State
21:41:30<roconnor>kau: depending on what you mean by time.
21:41:33<conal>all of functional programming is implemented via unsafePerformIO (by some name).
21:41:49<Twey>Ergo, unsafePerformIO is a compiler hook, not a part of Haskell.
21:41:55<kau>Berengal with what instead?
21:42:08<conal>Twey: indeed!
21:42:24<gwern>IO? in *my* 2+3?
21:42:51<augustss>gwern: not in your 2+3, because you never see the result :)
21:43:04<Berengal>kau: There are IORefs, which are mutable references living in the IO monad
21:43:04<Twey>Hehe
21:43:09<paper_cc>> let 2+3 = "IO" in 2+3
21:43:10<lambdabot> "IO"
21:43:12<gwern>augustss: dang it, you were supposed to say 'it's more likely than you think!'
21:43:17<conal>i mean things like side-effecting registers.
21:43:18<kau>roconnor: say user inputs
21:43:25<kau>Berengal: oh
21:43:36<Twey>> let 2+3 = print "hi" in 2+3
21:43:37<lambdabot> <IO ()>
21:43:50<SubStack>what
21:43:55<jkramer>Hello, I have another newbie question
21:44:08<augustss>> let 2+3 = "Hello" in 2+3
21:44:09<lambdabot> "Hello"
21:44:14<kau>Berengal: thats the way to do it? i missed that! ;)
21:44:15<gwern>SubStack: it's lambdabot's l33t security measures
21:44:16<jkramer>When I have a rather complex data type and I want to change a single element
21:44:44<jkramer>Is there a nice way to do it or should I make a constructor that copies all the other values and only sets the one I change?
21:44:46<SubStack>I am more boggled by the ability to define 2+3 like that
21:44:51<Berengal>> let 2+2 = 5; a+b = a - (-b); fibs = 1:1:zipWith (+) fibs in sum (take 10 fibs)
21:44:52<lambdabot> Couldn't match expected type `[t]'
21:44:56<Berengal>:/
21:45:08<Berengal>kau: That's one way to do it
21:45:08<jmcarthur_work>jkramer, look into records?
21:45:12<byorgey>jkramer: there is a nice way to do it if you have given the elements of the structure names using record syntax.
21:45:13<sjanssen>jkramer: you can use record syntax
21:45:14<BONUS>or zippers
21:45:24<byorgey>i.e. data Foo = { x :: Int, y :: Double, z :: Char }
21:45:41<kau>jkramer: there is someting like let a = rec { foo = "toto"}
21:45:42<byorgey>jkramer: then if f :: Foo, you can change just the x field of f by f { x = 6 }
21:45:57<roconnor>jkramer: also see the Data.Accessor package.
21:46:31<jkramer>If record syntax is the :: Type-stuff then I'm already using it :)
21:47:11<gwern>no, records are more like {}
21:47:28<jkramer>Like: data Foo = Foo { something :: String } deriving ...
21:47:37<paper_cc>jkramer: that's it
21:47:39<byorgey>yup, that's record syntax
21:47:42<jkramer>\o/
21:47:49<byorgey>jkramer: as opposed to just data Foo = Foo String
21:48:14<Axman6>jkramer: nice thing about it is you can still pattern match on those datatypes too
21:48:39<paper_cc>jkramer: you can then write things like \(foo :: Foo) -> foo { something = "changedValue" }
21:49:16<jkramer>I'll try it, wait a second :)
21:49:18<Axman6>so you can have data Vec = V {x,y,z :: Double}, and you can still have a function f :: Vec -> Double; f (V a b c) = a + b + c
21:49:25<Jedai>Axman6: and contruct them the same way you always did... In fact record syntax is more or less just syntax sugar over algebraic data types
21:49:34<Axman6>yup
21:50:07<BONUS>do {handle <- ContT $ withFile "foo.txt" ReadMode; lift $ putStrLn "blah"; ...
21:50:12<BONUS>learned this trick today here
21:50:14<BONUS>pretty cool :]
21:50:21<Axman6>so you can also say V 1.0 2.5 3.7, which is the same as V { x = 1.0, y = 2.5, z = 3.7}
21:50:21<Jedai>but you can also do "f (V {y = yv}) = yv + 3
21:50:39<BONUS>never thought of withFile as returning a CPS transformed value
21:50:40<Axman6>:o
21:50:55<paper_cc>@ty ContT
21:50:56<lambdabot>forall a (m :: * -> *) r. ((a -> m r) -> m r) -> ContT r m a
21:51:08<paper_cc>wow
21:51:13<kau>are "IOref" academic? i didn't came across it since i began with haskell that's why i'm asking lol
21:51:29<paper_cc>@google Monadic state transformers
21:51:29<Jedai>What's funny is that with GHC at least, you can use the special pattern "Contructor {}" even with datatypes that don't use record syntax
21:51:30<lambdabot>http://en.wikibooks.org/wiki/Haskell/Monad_transformers
21:51:32<Axman6>kau: i don't understand what you mean
21:51:53<kau>are IOref safe?
21:51:55<jkramer>Hmm, I don't completely get it. I have: updateSessionInput session newInput = UserSession { userInput = newInput }
21:51:56<Axman6>they're pretty widely used, the OpenGL bindings use them a lot
21:52:10<jkramer>Now I get a lot of warnings that everything but userInput is uninitialized
21:52:14<jkramer>Did I mis something
21:52:14<jkramer>?
21:52:15<Jedai>kau: IORef, academic ? IORef are pretty much like normal variables in imperative languages
21:52:24<kau>and good programming style ;)
21:52:25<Axman6>Jedai: replace the UserSession with session
21:52:32<Jedai>kau: they're as "safe" as those always are
21:52:43<O_4>s/Jedai/jkramer/
21:52:46<jkramer>Yay, works!3! \o/
21:52:51<jkramer>Thanks a lot :)
21:52:56<Axman6>uh yeah, sorry. meant jkramer
21:53:02<jkramer>I have no Idea where the 3! came from
21:53:39<kau>Jedai, Axman6: ok i see
21:53:51<Axman6>kau: MVars are far more interesting imo
21:54:10<kau>Axman6: i'll have a look;)
21:54:25<paper_cc>IORef -> MVar -> TVar -> ?
21:54:33<Axman6>MVars let you do pretty safe and fast concurrency
21:54:44<Axman6>TMvar ;)
21:56:40<kau>i have to go, thanks a lot for your answers!!!
21:56:44<conal>paper_cc: -> NoVar
21:56:46<Axman6>kau: also, if you feel you need to use mtuable variables, check out the ST monad. it's basically the IO monad without all the dangerous stuff
21:57:50<paper_cc>conal: -> Behavior ?
21:58:09<conal>paper_cc: yeah!
22:02:28<FunctorSalad>any ideas what this could be? "error: macro "hsc_const" passed 2 arguments, but takes just 1"
22:02:40<FunctorSalad>(when running hsc2hs on something generated by hsffig)
22:03:20<FunctorSalad>I know it's referring to a CPP macro, but why would it mismatch? :(
22:04:44<Axman6>what's the macro?
22:05:08<FunctorSalad>"hsc_const" - no idea what its purpose is
22:05:36<FunctorSalad>some version mismatch of hsffig and hsc2hs?
22:05:52<jkramer>Is there a nice way to check if there's input on a handle or EOF reached? hIsEOF seems to block until there's actually input or EOF, and if I do hWaitForInput first, it crashes when EOF is reached
22:07:07<FunctorSalad>I don't know of a *nice* way, but you could run either isEOF in a seperate thread, or run hWaitForInput and catch the exception
22:07:44<paper_cc>jkramer: maybe hReady?
22:08:15<jkramer>paper_cc: I think hReady would crash on EOF too
22:08:23<paper_cc>ACTION opens ghci
22:08:26<jkramer>FunctorSalad: How can I catch the exception?
22:08:34<jkramer>paper_cc: At least it says so in the docs
22:08:35<paper_cc>@hoogle catch
22:08:35<lambdabot>package catch
22:08:36<lambdabot>Prelude catch :: IO a -> (IOError -> IO a) -> IO a
22:08:36<lambdabot>Control.Exception catch :: IO a -> Exception -> IO a -> IO a
22:09:59<troutwine>Anybody have resources for stateful parsing with Parsec? (I'm parsing chess notation out of PGN files and would like the resulting AST to have absolute positioning.)
22:15:45<troutwine>Ah, seems Parsec has an embedded user state. Nevermind, then.
22:15:50<paper_cc>@ty \h -> (hReady h >> (return . Just)) `catch` (\e -> if isEOFError e then return Nothing else ioError e) -- the not-so-pretty way to solve jkramer's problem
22:15:51<lambdabot>Not in scope: `hReady'
22:15:51<lambdabot>Not in scope: `isEOFError'
22:17:49<dons>The Haskell Platform 2009.2.0.1 release is live: be a little bit more awesome today: http://hackage.haskell.org/platform/
22:19:00<sm>woot!
22:19:39<FunctorSalad>if anyone cares, the offending expression generated by hsffig (on which hsc2hs chokes) was "#const( 2 ), #const( 2 )"
22:19:47<dons>tell your friends. install haskell on their machines :)
22:19:53<FunctorSalad>apparently the preprocessor misinterprets the comma?
22:20:10<Badger>dons: or House? :P
22:21:28<troutwine>dons: Is the Haskell Platform not installing on Arch a known issue (wants happy 1.18.2, system has 1.18.4)?
22:21:47<sm>dons: are there release notes ? any word on the mac installer ?
22:22:17<dons>troutwine: Arch isn't updated yet (look at the version)
22:22:22<dons>working on it NOW, troutwine
22:22:36<dons>sm, mac installer close. i'll put up some release notes.
22:22:49<dons>http://trac.haskell.org/haskell-platform/wiki/2009.2#CandidatesforUpgradein2009.2.0.1
22:22:52<sm>fantastic, thanks a lot for working on this
22:22:53<dons>release notes ^^
22:23:05<sm>this = HP
22:23:12<troutwine>dons: Woops, quite true. My apologies.