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:04 | <Saizan> | ah :) |
| 00:01:07 | <QtPlaty[HireMe]> | duaneb: Shouldn't the IO monad prevent that? |
| 00:01:40 | <QtPlaty[HireMe]> | Oh figurering out is pure? |
| 00:01:47 | <duaneb> | QtPlaty[HireMe]: yes :P |
| 00:02:12 | <neoswish> | is default keyword only for Num class? |
| 00:02:14 | <duaneb> | oh great |
| 00:02:27 | <duaneb> | haskell doesn't throw an exception on divide by zero!? |
| 00:02:40 | <roconnor> | > 1 `div` 0 |
| 00:02:41 | <lambdabot> | * Exception: divide by zero |
| 00:03:12 | <duaneb> | yea, but > 1 / 0 |
| 00:03:13 | <copumpki> | what do messages along the lines of "Warning: Data.Array.Vector: unsafeFreezeMU is exported separately but will be documented under UA. Consider exporting it together with its parent(s) for code clarity." mean? |
| 00:03:14 | <duaneb> | > 1 / 0 |
| 00:03:15 | <lambdabot> | Infinity |
| 00:03:26 | <vixey> | have you noticed the people that like TCO call it TCO and the people against it call it TRE? |
| 00:03:27 | <duaneb> | plus, div is probably integral |
| 00:03:32 | <duaneb> | @type div |
| 00:03:33 | <lambdabot> | forall a. (Integral a) => a -> a -> a |
| 00:03:36 | <duaneb> | see? |
| 00:03:38 | <duaneb> | great. |
| 00:03:42 | <roconnor> | vixey: I have |
| 00:03:58 | <roconnor> | duaneb: what do you get when you do 1.0 / 0.0 in C? |
| 00:03:59 | <duaneb> | anyway, 1 / 0 should be NaN, not Infinity |
| 00:04:05 | <duaneb> | roconnor: I'll check |
| 00:04:11 | <roconnor> | duaneb: tell that to the IEEE |
| 00:04:20 | <augustss_> | duaneb: IEEE says it's infinity |
| 00:04:34 | <augustss_> | Which may or may not raise an exception. |
| 00:04:54 | <dolio> | vixey: Don't the people who like it call it 'proper tail recursion'? :) |
| 00:04:57 | <duaneb> | IEEE needs to take algebra again. |
| 00:05:07 | <dolio> | Or is that just Scheme bigwigs? |
| 00:05:20 | <augustss_> | IEEE floating point fails on most algebraic properties |
| 00:05:35 | <augustss_> | Like associativity |
| 00:05:39 | <duaneb> | dolio: no, those are the people who don't understand what TCO *is* |
| 00:05:39 | <copumpki> | dons: would it be bad to define andU/orU/allU/anyU in UArr in terms of foldr, so it can short-circuit and match List behavior more? |
| 00:05:40 | <Gracenotes> | it is a very extremely useful tool though |
| 00:05:42 | <roconnor> | dolio: I wonder if proper tail recursion is something different, something about how the "function call" is handled rather than about stack allocation? |
| 00:05:52 | <Gracenotes> | well. very. maybe not very extremely. |
| 00:05:55 | <MyCatVerbs> | duaneb: no, the IEEE 754 committee knew exactly that they were doing. It's designed for numerical simulation of physical processes, not algebra. |
| 00:06:11 | <dolio> | duaneb: The scheme standard calls it "proper tail recursion". |
| 00:06:28 | <Gracenotes> | IEEE has the most precision for lower numbers, where people are more apt to use it |
| 00:06:37 | <copumpki> | duaneb: there are a lot more painful things in IEEE than just that :) but it's still very useful for practical applications |
| 00:07:12 | <Gracenotes> | if you want something like computable reals, go ahead, but also be prepared to pay the price in performance... >_> |
| 00:07:16 | <Gracenotes> | *the IEEE mafia strikes again* |
| 00:07:21 | <dolio> | roconnor: Well, I read some newsgroup discussion where a guy was claiming that "proper tail recursion" is a stronger property than what you get with "tail call optimization", but I haven't gotten to his paper yet. |
| 00:07:29 | <copumpki> | :o |
| 00:07:54 | <roconnor> | dolio: I would guess that, but I'm only inferring that from the name and a bit of context. |
| 00:07:58 | <dolio> | roconnor: Something about proper tail recursion preventing you from doing stack allocation of variables at all, in some cases, or something. |
| 00:08:09 | <copumpki> | lol |
| 00:08:44 | <roconnor> | dolio: I could believe that. No need to free a stack and allocate it again, just reuse it. |
| 00:09:14 | <Gracenotes> | how I love cocoa with my pumpkin pie! |
| 00:09:16 | <Gracenotes> | ACTION bakes cocopumpkin |
| 00:09:19 | <copumpki> | :o |
| 00:09:44 | <cocopumpkin> | :O |
| 00:10:20 | <cocopumpkin> | A coCoconut is just a conut. |
| 00:10:30 | <copumpki> | I have quickcheck 2.1 installed in my user cabal dir, and 1.2 in the system |
| 00:10:42 | <duaneb> | @type or |
| 00:10:42 | <Saizan> | and a coconut is just a nut? |
| 00:10:43 | <lambdabot> | [Bool] -> Bool |
| 00:10:44 | <kacper_> | I write structural induction proof for reverse( reverse xs ) = xs and its good for finite list. I know that for infinite it should fail but i considering a case reverse( reverse _|_ ) => reverse( _|_ ) => _|_ and its look like good, who knows where induction for infinite lists fails? |
| 00:10:45 | <copumpki> | and it's complaining that 1.2 doesn't have what I need, when I want it to use 2.1 |
| 00:10:48 | <duaneb> | wtf? |
| 00:10:49 | <duaneb> | ok |
| 00:10:51 | <dolio> | roconnor: I'm not exactly sure how doing tail call optimization would fail to get you proper tail recursion though. Perhaps you can construct pathological examples where you get linear stack growth by referring to the contents of old stacks while using CPS or something. |
| 00:10:52 | <cocopumpkin> | Saizan, yes. :O |
| 00:10:59 | <dons> | copumpki: hmm. you want to short circuit the non-fused version? |
| 00:11:00 | <dons> | -- |/O(n)/. 'andU' yields the conjunction of a boolean array. |
| 00:11:00 | <dons> | andU :: UArr Bool -> Bool |
| 00:11:00 | <dons> | {-# INLINE andU #-} |
| 00:11:00 | <dons> | andU = foldU (&&) True |
| 00:11:10 | <Saizan> | copumpki: --user ? |
| 00:11:18 | <copumpki> | dons: well, I added a foldrU |
| 00:11:22 | <dolio> | roconnor: So even if you popped off stack frames, and allocated new ones, they'd be storing linearly increasing ammounts of variables or something. |
| 00:11:35 | <copumpki> | dons: that builds on a stream foldr |
| 00:11:45 | <kacper_> | I write structural induction proof for reverse( reverse xs ) = xs and its good for finite list. I know that for infinite it should fail but i considering a case reverse( reverse _|_ ) => reverse( _|_ ) => _|_ and its look like good, who knows where induction for infinite lists fails? |
| 00:11:59 | <dolio> | Which isn't allowed under proper tail recursion, which has to have bounded stack use for the particular case. |
| 00:12:03 | <roconnor> | dolio: I'm not claiming any change in space usage by proper tail recursion over TCO. |
| 00:12:05 | <dolio> | Constant bounded, that is. |
| 00:12:15 | <copumpki> | Saizan: I'm not using cabal for the compilation in this case :/ |
| 00:12:18 | <vixey> | kacper_: do you have proof rules for infinite structures? |
| 00:12:20 | <copumpki> | it's a plain makefile |
| 00:12:20 | <roconnor> | dolio: just a minor opitmization |
| 00:12:29 | <roconnor> | dolio: again, I'm sort of making all this up. I have no idea really |
| 00:12:49 | <ajdhs> | does anyone know how to use QuickCheck to get ahold of the value that caused a failure (I asked this earlier, but no answer.) |
| 00:12:49 | <kacper_> | vixey: no |
| 00:12:51 | <Saizan> | copumpki: are you running it as the same user? |
| 00:13:02 | <copumpki> | Saizan: yup, only got one user on this computer |
| 00:13:15 | <copumpki> | it seems to be looking at my system quickcheck |
| 00:13:33 | <MyCatVerbs> | dolio: IIRC one of the Schemes that does Cheney on the MTA just lets frames get allocated when you tail-call. |
| 00:13:35 | <dolio> | roconnor: He was claiming that TCO doesn't satisfy the space behavior of proper tail recursion, though. |
| 00:13:49 | <vixey> | kacper_: lets find some |
| 00:13:56 | <augustss_> | kacper_: Your particular case works, but what about, e.g., reverse (reverse (1:_|_))? |
| 00:14:13 | <vixey> | kacper_: for finite things you can do least fixed point induction, so on infinte things you get to do greatest fixed point induction |
| 00:14:24 | <roconnor> | dolio: okay, that's just crazy |
| 00:14:28 | <copumpki> | dons: I can leave it alone though, it isn't that important :) |
| 00:14:29 | <MyCatVerbs> | dolio: the allocated frames become garbage immediately on the next call, so that even though O(n) frames get allocated, only a constant number are ever live for the GC. |
| 00:14:46 | <rzezeski> | monadic_kid: You weren't lying, that's a great explanation of algebraic data types! It melted my mind a little though, I'm going to have to come back to it at a later date :) |
| 00:14:59 | <copumpki> | dons: I'm just cleaning up code in preparation to give you something for 0.2 |
| 00:15:13 | <MyCatVerbs> | dolio: the author justifies this implementation by pointing out that the Scheme standard only requires *amortised* O(1) space usage for tail recursive functions, not hard O(1) space usage. :3 |
| 00:15:14 | <kacper_> | vixey: could You give me any advice? |
| 00:15:32 | <dolio> | Anyhow, the paper is "Proper Tail Recursion and Space Efficiency" by Will Clinger. |
| 00:15:40 | <dolio> | I'm not sure if it goes into all that or not. |
| 00:17:32 | <kacper_> | augustss_: reverse( reverse (1:_|_) ) => _|_ /= (1:_|_) right? |
| 00:18:16 | <vixey> | kacper_: So the question is "what is induction for infinite objects" |
| 00:18:20 | <adamvo> | > reverse (reverse (1:undefined)) |
| 00:18:21 | <lambdabot> | * Exception: Prelude.undefined |
| 00:19:01 | <kacper_> | adamvo: so it fails because /= 1:undefine ? |
| 00:19:14 | <dons> | copumpki: i think the code as it is is fine. |
| 00:19:25 | <adamvo> | > reverse (reverse (1:undefined:[])) |
| 00:19:26 | <lambdabot> | [1,* Exception: Prelude.undefined |
| 00:19:30 | <dons> | happy to get e.g. IO /bytestring patches |
| 00:19:37 | <defun> | hey, how does polyparse compare to parsec? |
| 00:19:53 | <copumpki> | dons: okay, I'll just add a note in the documentation that points out the difference in behavior from list, maybe? |
| 00:20:08 | <Spreadsheet> | I'm new to Haskell. how do you print a number in haskell? |
| 00:20:34 | <copumpki> | Spreadsheet: print 1 |
| 00:20:36 | <kacper_> | vixey: i headr about coinduction, it is it? |
| 00:20:41 | <Spreadsheet> | copumpki: thanks |
| 00:20:44 | <kacper_> | *heard |
| 00:20:50 | <defun> | nobody? |
| 00:21:04 | <blackh> | Spreadsheet: 'putStrLn (show x)' is equivalent to 'print x' |
| 00:21:11 | <roconnor> | @src print |
| 00:21:11 | <lambdabot> | print x = putStrLn (show x) |
| 00:22:06 | <Spreadsheet> | thanks again |
| 00:22:23 | <augustss_> | kacper_: I think you can prove what you need by just fixpoint induction |
| 00:22:27 | <vixey> | kacper_: How do weapply coinduction to this example? |
| 00:22:30 | <dons> | copumpki: hmm. yes, it relies on fusion |
| 00:22:35 | <augustss_> | kacper_: but fixpoint induction is no fun |
| 00:22:42 | <dons> | copumpki: which is a bit weird |
| 00:22:48 | <copumpki> | hmm, how do you mean? |
| 00:23:37 | <kacper_> | vixey: I only heard that coinduction is for infinite structures |
| 00:23:57 | <ajdhs> | defun: I think polyparse is newer |
| 00:25:08 | <dolio> | Coinduction is for coinductively defined structures. |
| 00:25:15 | <dolio> | They aren't necessarily infinite. |
| 00:25:35 | <defun> | ajdhs: so, it is not neccessarily better or worse (than parsec). I assume that no one has tried using for a "real" project. Is there anything that would motivate me to use polyparse over parsec or vice versa? |
| 00:25:47 | <augustss_> | kacper_: http://www.utdallas.edu/~hamlen/cs6371fa08/lecture9.pdf |
| 00:27:10 | <augustss_> | kacper_: but that note doesn't mention the tedious part of showing that the predicate is admissable |
| 00:27:56 | <kacper_> | augustss_: it looks too hard for this exercice ;) |
| 00:28:01 | <sooth> | Is something wrong with code.haskell.org? |
| 00:28:50 | <augustss_> | kacper_: well, it's easy to show that reverse . reverse /= id since you can find a counter example. :) |
| 00:28:53 | <ajdhs> | defun: I believe it's used in HaXml |
| 00:28:54 | <jeffz`> | sooth: seems to be, I can't access trac |
| 00:29:17 | <ajdhs> | defun: Parsec is in the Haskell Platform and is probably more widespread |
| 00:29:54 | <copumpki> | bah |
| 00:30:06 | <kacper_> | yeah, as you wrote it is (1:undefine) but in my excercise i must show where induction's proof fails |
| 00:30:15 | <ajdhs> | defun: so it may be better supported |
| 00:30:27 | <ajdhs> | defun: I've never actually used PolyParse, so I can't give you a lot more detail than that. |
| 00:31:22 | <augustss_> | kacper_: but you can't use structural induction to prove things when _|_ is involved. |
| 00:31:33 | <defun> | thanks, mate. |
| 00:32:14 | <augustss_> | HaXml uses polyparse and can parse quite large files fast. |
| 00:32:22 | <kacper_> | so fixed-point induction ? |
| 00:33:22 | <jeffz`> | hm, I've installed the haskell platform, tried to use ghci with Hipmunk but ghci tries to load a nonexistent libm.dll |
| 00:33:50 | <copumpki> | ACTION screams at cabal |
| 00:33:55 | <augustss_> | kacper_: you can probably find where the induction fails pretty easily with fixed point induction |
| 00:34:15 | <augustss_> | copumpki: it can't hear you |
| 00:35:11 | <kw317> | hi |
| 00:35:29 | <copumpki> | :/ |
| 00:38:22 | <copumpki> | Properties/Utils.hs:15:7: |
| 00:38:22 | <copumpki> | Could not find module `Test.QuickCheck.Batch': |
| 00:38:22 | <copumpki> | it is a member of the hidden package `QuickCheck-1.2.0.0' |
| 00:38:52 | <SamB> | copumpki: what quickcheck is cabal using? |
| 00:38:53 | <SamB> | any ? |
| 00:39:00 | <copumpki> | this is from a makefile |
| 00:39:01 | <SamB> | if not, add it to the .cabal file ... |
| 00:39:06 | <SamB> | oh |
| 00:39:06 | <copumpki> | just a regular ghc build |
| 00:39:25 | <copumpki> | how can I express constraints on the command line? |
| 00:39:27 | <SamB> | ask in #ghc ? |
| 00:39:40 | <dons> | --constraint='base<43' |
| 00:45:19 | <coCoconut> | pumpkin_: "In Cabal-space, no one can hear you scream." ;p |
| 00:47:21 | <Rambling> | In Python, I can use tuples and lists interchangeably with function like sum: sum((1,2)) and sum([1,2]) both work. How can I sum the elements of a tuple in Haskell? |
| 00:47:41 | <vixey> | Rambling: sumTuple (x,y) = x + y |
| 00:47:44 | <pumpkin_> | you can't work with tuples of arbitrary sizes |
| 00:47:45 | <lambdabot> | pumpkin_: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 00:47:47 | <pumpkin_> | uncurry (+) |
| 00:47:47 | <vixey> | Rambling: sumTuple = uncurry (+) |
| 00:48:17 | <vixey> | Rambling: if you wanted to write a function that works on tuples as well as lists you could use typeclasses - it's not normal haskell though |
| 00:49:01 | <Rambling> | What about summing a 3-tuple? |
| 00:49:04 | <Cale> | Rambling: It's just very uncommon to use tuples for something you're going to want to sum. The elements of a tuple may be of various different types anyway. |
| 00:49:22 | <Cale> | Also, 3-tuples are uncommon and 4-tuples and higher are usually to be avoided. |
| 00:49:43 | <Cale> | When you start getting larger numbers of components, defining your own datatype is usually best. |
| 00:50:02 | <MyCatVerbs> | Cale: ...I have learned that last bit the hard way. :) |
| 00:50:04 | <Cale> | But, you can say (\(x,y,z) -> x+y+z) |
| 00:50:05 | <Rambling> | Okay. I'm actually working on Project Euler Problem #9. |
| 00:50:37 | <Rambling> | So I was working with lists of 3 tuples to represent possible Pythagorean Triplets. |
| 00:50:50 | <jeffz`> | hm, ok, I thought this might have worked earlier, but windows ghci 6.8.2 also tries to load libm |
| 00:51:24 | <Cale> | So in that case, you actually probably want to write a function like (\(x,y,z) -> x^2 + y^2 == z^2) |
| 00:51:44 | <Cale> | (depending on how you choose to solve the problem) |
| 00:52:28 | <EvilTerran> | ACTION found a cleverly-written list comprehension to be the clearest way of doing that one, iirc |
| 00:53:15 | <Rambling> | Cale: I made a list of triplets of numbers whose sum was 1000 and filtered it using a function identical to that. |
| 00:53:22 | <Cale> | I haven't bothered to look at what the problem actually is, but yeah, a list comprehension is a nice way to generate Pythagorean triples if speed doesn't matter too much. |
| 00:53:51 | <pumpkin_> | Rambling: that sounds inefficient :P |
| 00:54:12 | <dolio> | Filtering by isPythagoreanTriple (x,y,z) is probably unadvisable, too. |
| 00:54:25 | <Cale> | But that's really not so many triples to check. |
| 00:54:46 | <dolio> | Rather than generating x and y and testing if x^2 + y^2 is square. |
| 00:54:55 | <solrize> | > do {x<-[1..999];y<-[x..999];let z=1000-x-y; guard $ x^2+y^2==z^2; return z} |
| 00:54:56 | <lambdabot> | <no location info>: parse error on input `;' |
| 00:54:59 | <cocopumpkin> | > [(2*m*n,m^2-n^2,1000-(2*m*n)-(m^2-n^2)) | m <- [2..], n <- [1..m], 2*m*n<m^2-n^2,2*m*n+(m^2-n^2)+(m^2+n^2)==1000] |
| 00:55:00 | <vixey> | obv. you should implement CHR then CLP/FD in terms of CHR and write the program using that |
| 00:55:11 | <solrize> | > do {x<-[1..999];y <-[x..999]; let z=1000-x-y; guard $ x^2+y^2==z^2; return z} |
| 00:55:13 | <lambdabot> | <no location info>: parse error on input `;' |
| 00:55:15 | <lambdabot> | thread killed |
| 00:55:18 | <cocopumpkin> | > head [(2*m*n,m^2-n^2,1000-(2*m*n)-(m^2-n^2)) | m <- [2..], n <- [1..m], 2*m*n<m^2-n^2,2*m*n+(m^2-n^2)+(m^2+n^2)==1000] |
| 00:55:20 | <lambdabot> | (200,375,425) |
| 00:55:21 | <solrize> | hmm |
| 00:55:41 | <cocopumpkin> | I guess lambdabot likes to spit out random numbers. ;) |
| 00:55:57 | <Cale> | Write a function to construct rationals, and then do a stereographic projection onto rational points on the unit circle ;) |
| 00:56:22 | <Rambling> | cocopumpkin: I had forgotten that you could do filtering inside of the list comprehension rather than using filter. |
| 00:57:14 | <roconnor> | > let rats = 1:concat [[x+1, 1/(x+1)]|x<-rats] in rats |
| 00:57:16 | <lambdabot> | [1.0,2.0,0.5,3.0,0.3333333333333333,1.5,0.6666666666666666,4.0,0.25,1.33333... |
| 00:57:20 | <pumpkin_> | do I need to do something to export instances from a module? |
| 00:57:29 | <roconnor> | > let rats = 1:concat [[x+1, 1/(x+1)]|x<-rats] in rats :: [Rational] |
| 00:57:30 | <lambdabot> | [1%1,2%1,1%2,3%1,1%3,3%2,2%3,4%1,1%4,4%3,3%4,5%2,2%5,5%3,3%5,5%1,1%5,5%4,4%... |
| 00:58:11 | <cocopumpkin> | > let rats = 1:concat [[x+1,1/(x+1)]|x<-rats] in scanr (*) 1 rats |
| 00:58:14 | <lambdabot> | [* Exception: stack overflow |
| 00:58:32 | <cocopumpkin> | > let rats = 1:concat [[x+1,1/(x+1)]|x<-rats] in scanl (*) 1 rats |
| 00:58:34 | <lambdabot> | [1.0,1.0,2.0,1.0,3.0,1.0,1.5,1.0,4.0,1.0,1.3333333333333333,1.0,2.5,1.0,1.6... |
| 00:59:32 | <cocopumpkin> | > let rats = 1:concat [[x+1,1/(x+1)]|x<-rats] in elemIndices 1 $ scanl (*) 1 rats |
| 00:59:36 | <lambdabot> | [0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51... |
| 00:59:43 | <cocopumpkin> | Odd. |
| 00:59:54 | <f1shb0t> | > let rats = 1:concat [[x+1,1/(x+1)]|x<-rats] in scanl (*) 1 rats |
| 00:59:56 | <lambdabot> | [1.0,1.0,2.0,1.0,3.0,1.0,1.5,1.0,4.0,1.0,1.3333333333333333,1.0,2.5,1.0,1.6... |
| 01:00:10 | <solrize> | [(x,y,z) | x<-[1..999], y<-[x..999], et z=1000-x-y, x^2+y^2==z^2] |
| 01:00:16 | <solrize> | > [(x,y,z) | x<-[1..999], y<-[x..999], et z=1000-x-y, x^2+y^2==z^2] |
| 01:00:17 | <lambdabot> | <no location info>: parse error on input `=' |
| 01:00:24 | <f1shb0t> | bonhoffer: It hooks directly to the kernel, bypassing anything else that might be messed up. The wiki link should explain it better though. |
| 01:00:24 | <solrize> | > [(x,y,z) | x<-[1..999], y<-[x..999], let z=1000-x-y, x^2+y^2==z^2] |
| 01:00:30 | <lambdabot> | [(200,375,425)] |
| 01:00:54 | <cocopumpkin> | lambdabot still likes to spit out random meaningless numbers. ;) |
| 01:00:55 | <dons> | Cale, roconnor seen mathlink (haskell lib)? |
| 01:00:55 | <f1shb0t> | > let rats = 1:concat [[x+1,1/(x+1)]|x<-rats] in scanl (*) 1 rats |
| 01:00:57 | <lambdabot> | [1.0,1.0,2.0,1.0,3.0,1.0,1.5,1.0,4.0,1.0,1.3333333333333333,1.0,2.5,1.0,1.6... |
| 01:01:24 | <f1shb0t> | hoohah: and after e.g. install gnome-desktop you can remove that specific package and run 'apt-get autoremove' so it removed all automatically installed packages related to an non-longer-installed package. |
| 01:01:25 | <ajdhs> | pumpkin_: no |
| 01:01:54 | <f1shb0t> | VERSION |
| 01:02:24 | <f1shb0t> | I get the following error when installing debian: Device /dev/hdc has multiple (0) logical sectors per physical sector. Any advice, info? I have no idea what this means. |
| 01:03:11 | <MyCatVerbs> | f1shb0t: it means you really, really need to be in #debian rather than #haskell. |
| 01:05:26 | <roconnor> | http://www.reddit.com/r/programming/comments/8kf9n/reply_to_randal_schwartz_on_dynamic_type_systems/c09n1qt |
| 01:05:51 | <roconnor> | Henry-Milner, why have you forsaken me? |
| 01:06:01 | <MyCatVerbs> | roconnor: Hindley. |
| 01:06:10 | <roconnor> | Hindley-Milner, why have you forsaken me? |
| 01:07:05 | <MyCatVerbs> | Because polymorphic recursion is actually a complete cow. |
| 01:07:16 | <roconnor> | cow? |
| 01:07:28 | <MyCatVerbs> | Pain in the neck. SML does not support it at all for very good reasons. |
| 01:07:28 | <monochrom> | Those who have learned from type system debates are bound to watch it repeat itself. |
| 01:07:40 | <roconnor> | very good reasons? |
| 01:08:07 | <Cale> | dons: I do remember hearing something about it. It looks neat, but I haven't tried it. |
| 01:09:10 | <augustss_> | Polymorphic recursion is a bit of a pain, but necessary for operating on the more interesting types. |
| 01:10:18 | <dolio> | Does SML allow nested types? |
| 01:10:36 | <roconnor> | dolio: I don't think so, but I'm not sure. |
| 01:10:42 | <Raevel> | what's a nested type? |
| 01:11:09 | <dolio> | Raevel: like 'data Foo a = Foo1 | Foo2 a (Foo (a,a))' |
| 01:11:26 | <augustss_> | dolio: yes, SML allows them |
| 01:11:28 | <Raevel> | you can do that in sml |
| 01:11:33 | <roconnor> | you can? |
| 01:11:48 | <dolio> | Wouldn't they be kind of a pain without polymorphic recursion? |
| 01:11:56 | <augustss_> | Very much so. |
| 01:12:03 | <MyCatVerbs> | dolio: why have Foo1 in there at all? Infinite doubling tuple streams! |
| 01:12:17 | <dolio> | :) |
| 01:12:29 | <Raevel> | datatype aexp = Add of aexp * aexp; |
| 01:13:01 | <PetRat> | Remind me what the record update syntax is? something like newRecord = oldRecord { field = newValue, field2 = newValue2 } |
| 01:13:14 | <MyCatVerbs> | PetRat: you have it exactly. |
| 01:13:18 | <solrize> | ; instead of , ? |
| 01:13:35 | <PetRat> | Great. |
| 01:13:37 | <MyCatVerbs> | I should check, but IIRC it's commas. |
| 01:13:44 | <solrize> | k |
| 01:13:59 | <kacper_> | > reverse( reverse undefined ) |
| 01:14:01 | <lambdabot> | * Exception: Prelude.undefined |
| 01:14:29 | <kacper_> | > reverse( reverse (1:2:undefined) ) |
| 01:14:31 | <lambdabot> | * Exception: Prelude.undefined |
| 01:14:47 | <kacper_> | > id (1:2:undefined) |
| 01:14:49 | <lambdabot> | [1,2* Exception: Prelude.undefined |
| 01:15:06 | <MyCatVerbs> | Yep, it's commas. |
| 01:16:16 | <PetRat> | Record syntax for definitions is also commas. Imagine that! Consistency! |
| 01:17:31 | <Cale> | but with do/let/case...of/where, it's semicolons |
| 01:17:59 | <PetRat> | do-notation is semicolons. I read the section in RWH where they say that some people call monads "programmable semicolons". I.e. in C or Java, a semicolon is a break between actions but does nothing itself. In Haskell, semicolons can be sophisticated. |
| 01:18:26 | <Baughn> | That's.. one way of putting it |
| 01:18:42 | <Cale> | > do x <- [1,2,3]; y <- [4,5]; return (x,y) |
| 01:18:44 | <lambdabot> | [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)] |
| 01:18:46 | <MyCatVerbs> | I think that makes sense, really. |
| 01:18:47 | <PetRat> | Baughn: not a good way? |
| 01:18:52 | <Baughn> | I'd /prefer/ saying that Monads are join, but that requires understanding functor and applicative first. ;) |
| 01:19:17 | <Cale> | don't forget poor return! |
| 01:19:21 | <MyCatVerbs> | If record syntax were semicolons instead of commas, you'd be able to confuse yourself by accidentally doing stupid things to them with line breaks. |
| 01:19:23 | <Baughn> | PetRat: Well, it works for a provisional understanding for the simpler kinds of monads. Or as a soundbite of great evil. |
| 01:19:26 | <PetRat> | I shouldn't have said monads ARE ..., but USING monads IS LIKE |
| 01:19:29 | <Baughn> | Cale: pure! |
| 01:19:43 | <Cale> | Oh, a monad is an applicative functor with join? :) |
| 01:19:51 | <PetRat> | I'm encountering a lot of evil soundbites then. |
| 01:19:53 | <Baughn> | Right. :) |
| 01:20:40 | <Baughn> | PetRat: Functor has fmap (<$>). Applicative has ap (<*>) and pure/return. Monad subclasses both of those, and adds join |
| 01:20:40 | <Cale> | I kind of like the return/(<=<) definition too |
| 01:20:59 | <MyCatVerbs> | :t (<=<) |
| 01:21:01 | <lambdabot> | forall b (m :: * -> *) c a. (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c |
| 01:21:04 | <Baughn> | PetRat: ..um, I'd suggest reading the typeclassopedia if you want to /understand/ that sentence |
| 01:21:14 | <Cale> | A monad is a functor m with return and (<=<) such that: |
| 01:21:20 | <Cale> | 1) return <=< f = f |
| 01:21:25 | <Cale> | 1) f <=< return = f |
| 01:21:30 | <Baughn> | The monad laws, sure.. |
| 01:21:37 | <Cale> | 1) (f <=< g) <=< h = f <=< (g <=< h) |
| 01:21:38 | <vixey> | :S |
| 01:21:42 | <Cale> | er, 1,2,3 ;) |
| 01:21:44 | <Baughn> | But those are just what's needed to make the syntax come out halfway sane |
| 01:21:49 | <MyCatVerbs> | Cale: I like your number Scheme. |
| 01:21:50 | <Cale> | ACTION was editing lines ;) |
| 01:21:53 | <vixey> | lol |
| 01:21:54 | <PetRat> | Yes, typeclassopedia is on my reading list. At the moment I'm trying to get through chapter 15 of RWH but it's tough to understand. I think it needs about twice as much explanatory text. Ratio of code to explanation is too high. |
| 01:21:55 | <Baughn> | They're not something you need to explicitly think about. ;) |
| 01:22:16 | <Baughn> | PetRat: Right, skip over to typeclassopedia, rejoin RWH later. :) |
| 01:22:50 | <PetRat> | Baughn: okey-dokey. |
| 01:23:12 | <amz> | ok, functional design question... say that I want to have a list of objects (say, stuff to draw on screen). I assume that the correct way to have this is to have each "object" (sorry for the OO lingo) contain a function that details how it's drawn... but how to have each contain its own set of data, which might be completely different? Should I pass that along to each's function? |
| 01:23:52 | <Cale> | amz: If all you're going to do is to draw them, then they *are* the actions to draw themselves on screen. |
| 01:24:11 | <PetRat> | The ultimate goal is to UNDERSTAND, and then flexible USAGE of the language comes from that. However, one can start USING the language by imitating examples, and understanding can develop over time. Or, one can try to UNDERSTAND before writing any of one's own code. Or both simultaneously. |
| 01:24:26 | <augustss_> | amz: If you have a fixed set of object that can be drawn then use a data type to define them. |
| 01:24:34 | <solrize> | amz, we'd tend to use separate types for the different object classes (beware, haskell uses "class" to mean what java would call an interface) |
| 01:24:42 | <Baughn> | amz: If you want something more transparent, then random data statements with a class Drawable and instances might be good enough |
| 01:24:43 | <amz> | well, no, I was thinking more along the lines of a game... so you'd have a list of entities that can be drawn (they'll return a drawing action once invoked), but they can also update themselves to the next step |
| 01:25:07 | <augustss_> | amz: I'd start with a data type |
| 01:25:07 | <amz> | but their updating routines are completely different |
| 01:25:07 | <solrize> | i.e. we'd have a function like draw :: (Drawable t) => t -> IO () |
| 01:25:14 | <amz> | and each has to keep its own different data |
| 01:25:39 | <amz> | and I don't want to have a different list for each different type of thing |
| 01:25:42 | <augustss_> | amz: You can also do it the OO way with existential types |
| 01:25:46 | <Baughn> | amz: Doesn't matter how different the implementation of draw is for each type, so long as its /interface/ (draw :: Drawable a => a -> IO ()) is the same |
| 01:26:17 | <MyCatVerbs> | amz: define a data type for them. You can use a sum data type that has an entry for every type of entity, or you can use existentials to imitate the OO way. |
| 01:26:37 | <Baughn> | ..or you could use plain old typeclasses |
| 01:27:19 | <solrize> | baughn, i see the problem, amz wants to have a list of drawables which might not all be the same type |
| 01:27:20 | <MyCatVerbs> | Baughn: not if you want to pass around a [forall a. (Drawable a) => a] |
| 01:27:39 | <Baughn> | Oh, but I'd probably end up defining some svg-like primitive drawing language and have "draw" convert to /that/ structure, which could then be manipulated more universally |
| 01:28:03 | <Baughn> | solrize: Ah. Then existentials.. or see my last sentence |
| 01:28:24 | <solrize> | baughn, right, are you saying there's a way to do it with just typeclasses and no existentials? |
| 01:28:31 | <amz> | well, see, I want to be able to do something like... nextworld = map (dostep) currentworld, and later drawaction = map (draw) nextworld |
| 01:28:34 | <Baughn> | draw :: Drawable a => a -> [DrawCommands] |
| 01:28:38 | <amz> | ok |
| 01:28:38 | <MyCatVerbs> | amz: take Breakout. You'd have something like: data Thing = Brick Brickdata | Ball Balldata | Paddle Paddledata, where Brickdata, Balldata and Paddledata are three different data structures defined elsewhere for the components. |
| 01:28:43 | <amz> | I'll look into that existentials thing |
| 01:28:50 | <Baughn> | scale :: DrawCommand -> Double -> DrawCommand, etc. Whatever. |
| 01:29:01 | <amz> | MyCatVerbs: I'm not sure if I like having to declare all of them together |
| 01:29:19 | <Baughn> | solrize: Sure, by reworking your design to not need multiple /different/ types in one list |
| 01:29:21 | <Cale> | You can also do the existential thing by hand |
| 01:29:25 | <Baughn> | solrize: Eg. by doing what I just suggested |
| 01:29:25 | <MyCatVerbs> | amz: the only real downside of doing it that way is that it's not extensible. |
| 01:29:34 | <Cale> | In this case, it's not hard to come up with an appropriate type... |
| 01:29:37 | <amz> | yes, that's my worry |
| 01:29:38 | <Cale> | Specifically... |
| 01:29:48 | <MyCatVerbs> | i.e. you can't add extra things without altering the definition of Thing. |
| 01:29:52 | <Baughn> | solrize: If you do use existentials, and the only thing you can do with them is to draw them, it seems pointless to not just have a list of whatever draw returns instead |
| 01:30:02 | <Baughn> | Of course, Drawable might have more functions, but still.. |
| 01:30:07 | <MyCatVerbs> | You could, on the other hand, come up with something more like: |
| 01:31:00 | <Cale> | (sorry, had to let cat out) |
| 01:31:02 | <amz> | I think drawing was a bad example... the "update" part is what I really worry about. For example, using Breakout... I have a list of Things containing the Paddle, the Ball, and a bunch of bricks |
| 01:31:05 | <MyCatVerbs> | class Entity e where { drawme :: e -> Shape, tickFunc :: e -> e, ... } |
| 01:31:09 | <amz> | then I map the "update" function over that list to get the next step |
| 01:31:14 | <solrize> | baughn, i don't get it, you've got a bunch of different stuff on the screen, why isn't it natural to put all that stuff in a list? |
| 01:31:16 | <MyCatVerbs> | And then data Paddle = ..., instance Entity Paddle where... |
| 01:31:37 | <MyCatVerbs> | Cale: I'm still here, :D |
| 01:31:39 | <amz> | but how will "update" access e.g. the velocity data that only the ball has? |
| 01:31:46 | <solrize> | and if you use an existential, how does the "draw" function know what it's drawing? |
| 01:31:46 | <amz> | (ok, paddle does too, but bricks don't) |
| 01:31:51 | <Cale> | data GameObject = GObj { next :: Stuff -> GameObject; draw :: IO () } |
| 01:32:12 | <Baughn> | solrize: Because most of the time, you want a /tree/ of drawables, not a list |
| 01:32:12 | <Cale> | Where Stuff is whatever appropriate parameters you want, maybe the World |
| 01:32:26 | <Baughn> | solrize: A window containing widgets containing.. |
| 01:32:27 | <Cale> | actually, you probably need a little more than this |
| 01:32:43 | <Cale> | Because the game objects have to be able to interact with each other |
| 01:32:44 | <Baughn> | solrize: Okay, you probably want open implementation for the widgets, in which case existentials do make sense |
| 01:32:50 | <solrize> | baughn, same issue, the drawables in the tree can be of different types |
| 01:32:52 | <solrize> | yeah |
| 01:33:03 | <Baughn> | solrize: However, if your class Drawable has only one method, then there's no point in using them. So obviously it has to have more |
| 01:33:06 | <amz> | interaction could be handled by having them return a list of messages on update |
| 01:33:08 | <solrize> | but, once something is existentially quantified, the type system loses track of what it is, right? |
| 01:33:13 | <Baughn> | But the only thing amz has suggested wanting to do is draw them |
| 01:33:13 | <amz> | which would be fed to the proper objects on the next step |
| 01:33:16 | <Baughn> | solrize: Yes |
| 01:33:26 | <MyCatVerbs> | amz: the typeclass way to do it is to have update be a typeclass member. The Paddle has its own definition of update, the Ball has another, the Blocks have another again... |
| 01:33:34 | <Cale> | amz: But does that recursive thing make sense? |
| 01:33:37 | <Baughn> | solrize: ..well, you could always use Dynamic or some such.. |
| 01:33:48 | <solrize> | ugh!!! :) |
| 01:33:52 | <Cale> | amz: Basically, the key is that records can contain functions which produce other records of the same type. |
| 01:33:56 | <amz> | MyCatVerbs: right, but then I couldn't map update over a list of those different types, right? |
| 01:34:27 | <Cale> | amz: Functions are extremely flexible in the data which they can involve in their definitions. |
| 01:34:44 | <MyCatVerbs> | amz: you could if you used an existential. |
| 01:35:02 | <amz> | something tells me that I'll really have to look into what are existentials :) |
| 01:35:02 | <solrize> | mycatverbs how does that work?? i think i am missing something |
| 01:35:14 | <Cale> | You don't necessarily need an existential |
| 01:35:20 | <solrize> | amz, existentials are a special case of gadt's so you may as well read about those instead |
| 01:35:29 | <Cale> | I think it's easier to grasp the normal functional programming solution. |
| 01:35:43 | <solrize> | i think the traditional way would be to use a sum type |
| 01:35:50 | <Cale> | Recursive types! |
| 01:35:53 | <solrize> | which means you have to declare all the sub-cases in one place |
| 01:36:00 | <Cale> | No, you shouldn't have to. |
| 01:36:12 | <amz> | well, Cale, for example... if I have a typeclass that defines "update :: a -> a", then I have a list of [myPaddle, myBall, brick1, brick2] :: [Things], and I "map (update) myList", I can't see how would update work |
| 01:36:43 | <Cale> | amz: Each game object consists of its own update function. |
| 01:36:44 | <MyCatVerbs> | solrize: map (update :: forall a. (Updateable a) => a -> a) $ (list :: [forall a. (Updateable a) => a] -- AFAIK actually works? ;P |
| 01:36:51 | <Cale> | amz: (along with whatever else you need) |
| 01:37:41 | <Cale> | amz: So to do the update, you just take each object, get out the update function and call it with whatever parameters are needed for it to generally do its work. |
| 01:37:42 | <solrize> | right, but the idea is you want a different update method for each type!!! you need something like generics |
| 01:38:02 | <Cale> | solrize: Yeah, but you can have functions which produce objects of a given type this way, just fine. |
| 01:38:24 | <Cale> | As far as the type system is concerned, it's all the same type. |
| 01:38:28 | <amz> | Cale: well, one of the "parameters" is the object in its true type... so each object's update function would have to have a (curried?) parameter pointing at itself so it knows what to work with? |
| 01:38:33 | <Cale> | The differences are in how the update function is written. |
| 01:38:34 | <Baughn> | solrize: The function that does the updates would have to have separate code for each type, then |
| 01:38:44 | <Baughn> | solrize: In which case you might as well use an ADT |
| 01:38:54 | <amz> | Baughn: well, that's fine, as long as I can declare them independent of each other |
| 01:39:01 | <amz> | *independently |
| 01:39:07 | <Cale> | amz: Actually, could you elaborate on what sort of game this is? |
| 01:39:18 | <solrize> | baughn, i mean the (update:: forall a. ...) scheme wouldn't be able to do something differently depending on a |
| 01:39:24 | <Cale> | amz: Just so I can be a little more concrete and complete about this. |
| 01:39:28 | <Baughn> | solrize: Exactly |
| 01:39:41 | <amz> | Cale: eh, it's not any game in particular (actually, I was thinking of doing a space invaders or something as a proof of concept)... I've been writing games in C++ for many years, trying to get my brain to work in Haskell now |
| 01:39:44 | <Cale> | There's no need for fancy type system features like existentials here, I think. |
| 01:39:49 | <solrize> | and if you use an ADT, then you have to have a single definition for it that enumerates all the cases |
| 01:40:08 | <solrize> | and if you do what cale says, it's sort of like writing in lisp :) |
| 01:40:22 | <Baughn> | Sure, but if you have a single update function for every type, then that function has to have a mention of each type anyway |
| 01:40:22 | <Cale> | Okay, let's try space invaders then. Each object needs: A way to draw it, a way to update it physically, and a way to determine if it intersects a given region of space. |
| 01:40:33 | <amz> | forget the collision stuff |
| 01:40:37 | <amz> | I'd rather handle that outside it |
| 01:40:48 | <amz> | let's just focus on individual objects with no concept of each other |
| 01:40:48 | <Cale> | Well, I'll leave it in for now, but very abstractly. |
| 01:40:56 | <Cale> | I'm not going to write the collision code ;) |
| 01:41:01 | <amz> | right ;) |
| 01:41:07 | <Cale> | So... |
| 01:41:24 | <amz> | so, what I WANTED to do is have a function that takes all objects in the world and returns a tuple of two lists |
| 01:41:31 | <amz> | the first list is what the world looks after the update |
| 01:41:40 | <amz> | and the second tuple is a list of messages that objects are sending to each other |
| 01:41:45 | <amz> | that will be processed before the next update |
| 01:41:48 | <Cale> | data Object = Obj { draw :: IO (); update :: Object; intersects :: Region -> Bool } |
| 01:41:58 | <Cale> | How does that look to you? |
| 01:42:22 | <amz> | sure, that looks right, if it works ;) |
| 01:42:26 | <Cale> | Possibly, we will want the update to take a list of the other objects. |
| 01:42:54 | <Cale> | So, let's write one of these... |
| 01:43:02 | <solrize> | interesects doesn't care where the object is? |
| 01:43:02 | <amz> | possibly, yes, but most of the need for that is for collision handling (at least, on this sort of game) |
| 01:43:08 | <amz> | which I'd handle outside the main update |
| 01:43:14 | <amz> | and send appropriate messages |
| 01:44:22 | <Cale> | rocket pos vel acc = Obj { draw = do ... ; update = rocket (pos + vel) (vel + acc) acc; intersects = \region -> ... } |
| 01:45:19 | <Cale> | that should probably be ^+^ ;) |
| 01:45:22 | <amz> | hrmm |
| 01:45:23 | <amz> | I see |
| 01:45:27 | <Cale> | (vector addition) |
| 01:45:36 | <Cale> | and inside draw and intersects, we have access to pos |
| 01:45:53 | <Cale> | (and vel, if we want) |
| 01:45:55 | <amz> | I didn't even know that syntax existed |
| 01:45:58 | <korpios> | (new to haskell here) If anyone is familiar with Network.Socket, why would I be getting an error "setSocketOption: invalid argument (Invalid argument)" from "setSocketOption someSocket NoDelay 1"? |
| 01:46:14 | <Cale> | amz: it's just the usual record syntax |
| 01:46:31 | <Cale> | amz: It's like normal algebraic datatypes, but with named fields |
| 01:46:34 | <amz> | I mean, I didn't know that functions declared inside the record could form a closure with the object's constructor's parameters |
| 01:46:38 | <amz> | [am I even using the right terms?] |
| 01:46:50 | <Lemonator> | is there an equivalent to mapM_ for Data.Map ? |
| 01:46:56 | <Cale> | Well, functions always capture the values of variables in the place that they're defined |
| 01:46:59 | <amz> | years of OOP have hardened my brain |
| 01:47:09 | <Baughn> | korpios: What OS would that be on? |
| 01:47:14 | <Baughn> | korpios: And a TCP or UDP socket? |
| 01:47:15 | <korpios> | Baughn: OS X |
| 01:47:18 | <Cale> | (as do all sorts of other data) |
| 01:47:20 | <sooth> | Anyone familiar with Language.C? |
| 01:47:21 | <solrize> | (mapM_ . Data.toList) ? |
| 01:47:33 | <Cale> | (like the IO action here, and other datastructures) |
| 01:47:48 | <solrize> | lemonator, (mapM_ . Data.Map.toList) i mean? |
| 01:47:56 | <Baughn> | korpios: TCP, UDP, what? |
| 01:48:00 | <Lemonator> | well, I'm using that right now, |
| 01:48:05 | <Lemonator> | but it seems inefficient. |
| 01:48:35 | <solrize> | inefficient? you have to traverse the map no matter what you do... |
| 01:48:38 | <korpios> | Baughn: I think it's TCP; trying to debug this: http://hackage.haskell.org/packages/archive/haskell-tyrant/0.2/doc/html/src/Database-TokyoTyrant.html#openConnection |
| 01:48:59 | <Lemonator> | but with that, I'm traversing it twice. |
| 01:49:10 | <Lemonator> | once to construct the list, and then again to map the function |
| 01:49:27 | <korpios> | tracked it down to that function, but not making much headway past that |
| 01:49:54 | <Cale> | Existentials would do a very similar thing here, but they extend to somewhat more complicated situations perhaps a bit more smoothly, and give you a more concrete way to represent the extra bunch of data which the methods are using. I can show you how that would look if you want. I don't think it's really much better than this way for any of the situations which would occur in a game. |
| 01:49:58 | <amz> | would this work? makerocket pos = let a = Obj { draw = drawrocket a; update = updaterocket a; } in a |
| 01:50:27 | <vixey> | amz: makeRocket, drawRocket etc |
| 01:50:28 | <Cale> | let a = x in a is always the same as x |
| 01:50:42 | <amz> | I thought Haskell didn't use camel case? o_o |
| 01:50:53 | <Cale> | It does, by convention |
| 01:50:55 | <amz> | Cale: yes, but I'm passing that same "a" to the functions |
| 01:50:56 | <Cale> | :t putStrLn |
| 01:50:57 | <lambdabot> | String -> IO () |
| 01:50:59 | <amz> | is that valid? |
| 01:51:00 | <Cale> | amz: oh, right. |
| 01:51:00 | <amz> | oh |
| 01:51:00 | <amz> | right |
| 01:51:01 | <amz> | duh |
| 01:51:03 | <Cale> | amz: Yes, it works. |
| 01:51:04 | <vixey> | amz: anyway that can't work because you didn't use pos |
| 01:51:26 | <amz> | er, yes, hrm |
| 01:51:32 | <Cale> | amz: But yeah, you need to pass the initial parameters in :) |
| 01:51:38 | <Baughn> | korpios: Well, try sticking a trace on it. The only way that should fail like that is if it's actually asking for a non-tcp socket. |
| 01:51:47 | <Cale> | amz: Basically, you can separate the working bits into a where clause nicely. |
| 01:52:02 | <Baughn> | korpios: Or, given that it's in IO already, just print the family, etc. |
| 01:52:15 | <korpios> | Baughn: I should've just pasted exactly what I'm trying: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4975 |
| 01:52:30 | <Cale> | rocket pos vel acc = Obj { draw = drawRocket; update = updateRocket } |
| 01:52:37 | <Cale> | where drawRocket = do ... |
| 01:52:51 | <Cale> | updateRocket = ... |
| 01:53:14 | <Cale> | That way, you'll have access to the parameters which rocket was called with, so you can make the recursive call easily. |
| 01:53:22 | <amz> | hrm |
| 01:53:25 | <amz> | I see, that makes sense |
| 01:53:50 | <Cale> | But for testing, it possibly makes sense to add parameters to those things, and separate them from the where. |
| 01:54:02 | <Cale> | I'm not sure which I'd like better :) |
| 01:54:35 | <Baughn> | korpios: Nope, can't say I get it. strace'd probably be useful, but.. |
| 01:54:39 | <Baughn> | ACTION goes to sleep |
| 01:54:44 | <amz> | well |
| 01:54:46 | <amz> | thanks everyone |
| 01:54:49 | <amz> | I'll give this a try later |
| 01:54:53 | <Cale> | great :) |
| 01:54:58 | <Cale> | Let us know how it goes |
| 01:55:30 | <amz> | If I can't get my brain around how to make a game in Haskell elegantly, I'll grow up to be a depressed old man |
| 01:55:36 | <amz> | because after tasting Haskell, C++ looks so... ugly |
| 01:55:42 | <amz> | and so does Java |
| 01:55:46 | <Cale> | The nice thing about this way is you get basically all the usual convenience of objects, as long as you can decide what your interface looks like. |
| 01:56:52 | <Cale> | However, it does make adding new operations into a chore, because you have to update each of these object-creating functions. |
| 01:57:01 | <Cale> | (but that's the same as in OO) |
| 01:58:30 | <solrize> | well, in OO you'd make subclasses |
| 01:59:10 | <solrize> | amz someone wrote a first person shooter in haskell... |
| 01:59:22 | <Saizan> | yeah, but if you have a bunch of subclasses and you add a method to the main class you need to modify all of them to add it |
| 01:59:48 | <Saizan> | in constrast, if you have an ADT and you want to add a function you just write it |
| 01:59:54 | <amz> | solrize: yes, I've heard, but I haven't looked at the source to see if it was done in a sane way :) |
| 02:00:04 | <amz> | no point in using Haskell if it were to make the job harder |
| 02:00:37 | <solrize> | saizan, you only have to modify the subclasses when they can't inherit |
| 02:03:04 | <Cale> | Oh, another suggestion, for a 2D game, complex numbers are the way to go for coordinates. |
| 02:04:00 | <Cale> | You get the vector operations trivially (addition, scalar multiply), and then by multiplying by exp(0:+theta), you get rotation for free as well. |
| 02:04:46 | <Cale> | > exp (0:+pi/4) |
| 02:04:47 | <lambdabot> | 0.7071067811865476 :+ 0.7071067811865475 |
| 02:04:52 | <monochrom> | "expression problem" |
| 02:05:01 | <Cale> | > exp (0:+pi/4) * (3 :+ 4) |
| 02:05:02 | <solrize> | for 3D you can use quaternions the same way |
| 02:05:02 | <lambdabot> | (-0.707106781186547) :+ 4.949747468305833 |
| 02:05:26 | <Cale> | solrize: yeah :) |
| 02:05:49 | <Cale> | (more or less -- it's not quite as beautiful, but nearly so) |
| 02:08:10 | <amz> | Cale: in my experience, you almost never need real rotation in 2D games, anyway |
| 02:08:31 | <amz> | what I usually do is just rotate a normalized vector, and scale that by the force I'm applying |
| 02:08:40 | <amz> | and, from that point on, no more rotations are involved |
| 02:08:51 | <amz> | [except graphically, which is handled by gl/d3d] |
| 02:10:14 | <Cale> | amz: Yeah, but the exp function is so convenient :) |
| 02:11:12 | <Cale> | amz: For an asteroids-style game I'd expect it's pretty important to rotate things easily too... |
| 02:11:47 | <amz> | well, if the asteroids are represented as actual polygons, logics-wise, yes |
| 02:11:48 | <Cale> | (if left/right keys turn the player's ship, and you have lots of spinning asteroid objects :) |
| 02:12:04 | <amz> | but the player's ship falls under the case I mentioned |
| 02:12:09 | <amz> | you just thrust in the direction you're facing |
| 02:12:16 | <amz> | after that, you don't need to worry about rotations anymore |
| 02:12:20 | <Cale> | What about the geometry for the player's ship though? |
| 02:12:29 | <amz> | I'd represent it as a circle ;) |
| 02:12:33 | <Cale> | ah, hehe |
| 02:12:55 | <amz> | one thing that I learned from japanese "maniac shooters" is that having a small collision area on player's "ship" is a good idea |
| 02:13:06 | <amz> | it's usually a small circle on its center |
| 02:13:25 | <amz> | it lets you have more bullets on the screen without making the game impossibly hard |
| 02:14:00 | <amz> | extreme example: http://upload.wikimedia.org/wikipedia/en/2/24/PCByukari140.jpg |
| 02:14:16 | <Cale> | But if the controls are such that you have keys to turn and then a thruster, like the original asteroids, you'd definitely want to draw something which isn't rotationally symmetric |
| 02:14:27 | <mauke> | not nearly enough objects :-) |
| 02:14:51 | <amz> | Cale: ah, yes, but I'd just draw it facing right and use glRotate() to take care of the rest ;) |
| 02:15:55 | <Cale> | I suppose that is quite doable. |
| 02:17:04 | <amz> | heh, funny... now that I linked to that pic, I was looking the attack pattern on youtube, and noticed that several of the other attack patterns would be constructed with quite a lot of rotation |
| 02:17:06 | <amz> | so I stand corrected |
| 02:18:38 | <Cale> | rRootage is a good free game of that sort :) |
| 02:19:14 | <amz> | what sort? |
| 02:23:33 | <Cale> | Japanese style shooter |
| 02:23:42 | <Cale> | With lots of objects :) |
| 02:23:46 | <amz> | :D |
| 02:23:48 | <amz> | ACTION looks into it |
| 02:24:39 | <amz> | hah, they invented a language to describe the bullet patterns |
| 02:25:10 | <ajdhs> | is there a way to generate the tested values based on the failure value of a QuickCheck test? |
| 02:25:27 | <ajdhs> | (besides copying and pasting the printed value?) |
| 02:26:14 | <roconnor> | @check \x -> x == 0 |
| 02:26:15 | <lambdabot> | "Falsifiable, after 0 tests:\n1\n" |
| 02:26:33 | <roconnor> | 1 |
| 02:26:52 | <roconnor> | ACTION cut and paste |
| 02:26:52 | <Asztal> | @check \x y -> x == y |
| 02:26:53 | <lambdabot> | "OK, passed 500 tests." |
| 02:27:00 | <ajdhs> | yeah |
| 02:27:10 | <Cale> | amz: And a genetic programming tool for creating patterns |
| 02:27:33 | <ajdhs> | but suppose it was a more complicated expression |
| 02:27:52 | <ajdhs> | and it was infeasible to cut and past it |
| 02:27:56 | <Saizan> | ajdhs: use QuickCheck-2 |
| 02:28:00 | <ajdhs> | I have that |
| 02:28:21 | <ajdhs> | but I can't figure out how to get the failed values out of it |
| 02:29:13 | <ajdhs> | for example |
| 02:29:15 | <ajdhs> | if I have |
| 02:29:37 | <ajdhs> | @check \x y -> sum x > 100000 |
| 02:29:38 | <lambdabot> | "Falsifiable, after 0 tests:\n[]\n()\n" |
| 02:29:45 | <ajdhs> | @check \x y -> sum x < 100000 |
| 02:29:47 | <lambdabot> | "OK, passed 500 tests." |
| 02:29:51 | <ajdhs> | @check \x y -> sum x < 100 |
| 02:29:52 | <lambdabot> | "Falsifiable, after 76 tests:\n[-22,6,6,34,17,18,16,26,25,10,10,-16,14,-29,... |
| 02:29:55 | <ajdhs> | @check \x y -> sum x < 1000 |
| 02:29:57 | <lambdabot> | "Falsifiable, after 298 tests:\n[124,27,-27,-27,100,-128,-97,72,-115,92,-45... |
| 02:30:04 | <ajdhs> | then that's a really long list to copy back in |
| 02:30:11 | <ajdhs> | also, in my case, it's really a Data.Map.Map |
| 02:30:18 | <ajdhs> | with lots of quotation marks and stuff |
| 02:30:23 | <ajdhs> | so it's a pain to copy and paste... |
| 02:31:46 | <Saizan> | you can put it in a file and use read |
| 02:33:16 | <ajdhs> | hm |
| 02:33:17 | <ajdhs> | yeah |
| 02:33:24 | <ajdhs> | I guess that's what I'll have to do |
| 02:34:46 | <Gracenotes> | hm. I have a monad that's like the state monad, but is actually a ReaderT IO that use an MVar for get and put. Is there a good way to start a thread that needs the MVar immediately, but also somehow put its ID into the MVar? |
| 02:35:04 | <Gracenotes> | using a (Maybe ThreadId) would take care of this, but it seems a bit hacky |
| 02:35:26 | <Gracenotes> | hm... mdo perhaps would be a good way. Seems a bit much though. |
| 02:35:41 | <hydo> | What is the general method for uninstalling a cabal package? I can't believe that everyone deletes ~/.ghc and ~/.cabal when things get really borked up. |
| 02:35:55 | <bd_> | Gracenotes: You could just put the threadid in the mvar after it starts. If it tries to take the mvar it'll just block. |
| 02:36:32 | <roconnor> | mdo is always a good way. :) |
| 02:36:35 | <mauke> | hydo: unregister it, then rm the library files |
| 02:36:50 | <hydo> | unregister with ghc-pkg, correct? |
| 02:36:54 | <Gracenotes> | oh, hm, that's right. The issue is that the MVar access is not direct, but through get and put. |
| 02:37:25 | <Gracenotes> | (get using readMVar) |
| 02:38:16 | <Saizan> | Gracenotes: forkR action = do var <- ask; id <- forkIO (runReaderT action var); put id |
| 02:38:39 | <Gracenotes> | Saizan: I already have a function that does that |
| 02:39:03 | <Saizan> | what's the problem with it? |
| 02:39:06 | <Gracenotes> | in fact, it's a typeclass, MonadFork, with fork :: m () -> m ThreadId |
| 02:39:37 | <Saizan> | then, \m -> id <- fork m; put id |
| 02:39:47 | <Gracenotes> | the issue is not starting the new thread, but rather putting the ThreadId into the MVar, when the ThreadId is not the only member of the MVar |
| 02:40:12 | <Gracenotes> | and other members of the MVar are needed immediately by the new threade |
| 02:40:13 | <Gracenotes> | -e |
| 02:40:29 | <Saizan> | oh, that's different |
| 02:40:43 | <Saizan> | i'd use a tuple of MVars probably |
| 02:40:46 | <Gracenotes> | I suppose I could have a half-second pause in the new thread. A bit suspect, though. |
| 02:41:29 | <Gracenotes> | hm. Or, having an MVar in the MVar |
| 02:42:00 | <Gracenotes> | or, as I said, a Maybe ThreadId. |
| 02:42:58 | <Saizan> | or mdo and pass the id as an argument |
| 02:43:07 | <Gracenotes> | argh. When you design something to be extensible, the lack of extensibility reveals itself to you the quickest |
| 02:43:57 | <roconnor> | mfix (\id -> newMVar id >>= \var -> forkIO (runReaderT action var)) |
| 02:43:57 | <Saizan> | heh, maybe you want to use something like lenses |
| 02:44:47 | <Gracenotes> | roconnor: I'd use mdo. In fact I've already written something up using mdo. But there should be a better way... |
| 02:44:57 | <roconnor> | why should there be a better way? |
| 02:45:38 | <Gracenotes> | well, it's an IRC framework I've been working on-and-off about. If the user needs mdo to make it work... well... that's not a good start. |
| 02:46:51 | <Gracenotes> | then again it is also a general problem, of having all the data related to a game include the thread id, which is necessary for externally shutting it down |
| 02:47:02 | <roconnor> | Gracenotes: mfix plays a central roll in Oleg's object oriented framework |
| 02:47:11 | <roconnor> | you shouldn't fear it |
| 02:48:29 | <Elly> | hm, oleg has an OO framework? |
| 02:48:42 | <Gracenotes> | then... there's central role vs. hack to get around flaws in design. I'll play around with it a bit more. |
| 02:48:51 | <roconnor> | forkIO (myThreadId >>= newMVar >>= (runReaderT action) |
| 02:48:55 | <roconnor> | ) |
| 02:51:38 | <Gracenotes> | in Java, it would be possible for the game to extend the Thread object. here it exists as a separate data object. Things couple differently in different languages, of course :) |
| 02:52:57 | <roconnor> | Gracenotes: what's wrong with using myTreadId to get the ThreadId at the beginning when the MVar is initiated? |
| 02:55:48 | <Gracenotes> | the thread id is not the only thing in the MVar. But, myThreadId would at least work, and I don't think any race conditions would result (although certainly possible). Keeping in mind that this isn't in IO, but a MonadIO, so just lifting would be needed. |
| 02:56:15 | <Gracenotes> | at least the race condition wouldn't happen in the game thread |
| 02:57:47 | <roconnor> | hmm, I guess I don't understand what you are doing. |
| 02:59:33 | <Gracenotes> | monad transformer stacks can do that to people |
| 03:01:46 | <Gracenotes> | the idea of the startGame function is, given some information available to configure a game, do the configuration (reading from files and sucih), store that in the Game data object (which includes score-keeping maps and game data) and start the thread that does the game |
| 03:02:27 | <Gracenotes> | the issue is that the function calling startGame will need access to the thread id, in order to kill it if requested (i.e. !stop) |
| 03:03:27 | <Gracenotes> | hm... I suppose I don't have to store the thread ID in the Game object... but keeping track of it is its own issue |
| 03:04:07 | <Elly> | is oleg just like... a professional bad person? |
| 03:04:20 | <Gracenotes> | >_> |
| 03:05:24 | <monochrom> | oleg is a professional good person |
| 03:06:19 | <SamB> | Elly: http://arcanux.org/lambdacats_3.html#entry4 <- you mean this oleg ? |
| 03:06:45 | <Elly> | monochrom: Oleg is the mirror that shows a normal person that they are stupid :P |
| 03:06:53 | <Elly> | SamB: probably :P |
| 03:07:06 | <Gracenotes> | ooh. there is a third lambdacats page? |
| 03:07:30 | <SamB> | Gracenotes: the new cats will be on the first one |
| 03:07:36 | <Gracenotes> | yes |
| 03:07:58 | <Gracenotes> | oh, and there are yet older ones |
| 03:08:25 | <SamB> | I do wish that site had permalinks, though :-( |
| 03:11:44 | <jinjing> | @seen snoyman |
| 03:11:44 | <lambdabot> | I haven't seen snoyman. |
| 03:14:28 | <Elly> | hmm |
| 03:14:37 | <Elly> | I need a big project to do this summer in either haskell or scheme |
| 03:14:43 | <Elly> | I don't know either of those languages well enough |
| 03:15:17 | <SamB> | Elly: why do you need a big project ? |
| 03:15:26 | <hatds> | (obvious comment about the "write yourself a scheme implementation" haskell tutorial) |
| 03:15:38 | <Elly> | SamB: I don't have time for them during the school year |
| 03:15:57 | <SamB> | ACTION wonders how Elly manages not to get tons of chores in the summer |
| 03:16:09 | <Elly> | I have a job :P |
| 03:16:31 | <Elly> | I don't live with my parents, so there's nobody to hand me chores |
| 03:17:33 | <hydo> | Ugh, I know I've read about it probably 10 times, but I can't remember and I'm not finding much on google.... what does the ! signify in "data DeliciousState = DeliciousState ![D.Post] !UTCTime" |
| 03:18:13 | <monochrom> | http://www.vex.net/~trebla/haskell/strict-field.xhtml |
| 03:18:36 | <hydo> | monochrom: awesome, thank you! |
| 03:18:50 | <hydo> | bookmarked for the next time my brain takes a vacation on me. ;) |
| 03:21:53 | <Elly> | hm |
| 03:21:58 | <Elly> | I could do the write-yourself-a-scheme one |
| 03:22:01 | <Elly> | that might be fun :) |
| 03:23:43 | <monochrom> | write yourself a résumé that says you know haskell and you are done with all the profitable languages and tools and paradigms and agile whatever. |
| 03:24:56 | <Elly> | the only language I feel comfortable saying I understand deeply is C :\ |
| 03:25:38 | <monochrom> | You mean you know how to evalute 2["heya"] ? |
| 03:28:15 | <Elly> | I do, in fact, know what that does |
| 03:28:19 | <Elly> | it's 'y' |
| 03:28:33 | <SamB> | or that it's okay to say sizeof (struct { int foo; int bar; }) ? |
| 03:28:50 | <Elly> | I know that sizeof does not necessarily evaluate any part of its argument, yes |
| 03:29:04 | <Elly> | I also know about sizeof(*(int*)NULL) |
| 03:29:12 | <SamB> | ACTION tried to look it up when someone asked that in ##c the other day ... |
| 03:29:39 | <Elly> | that sizeof you gave has to work, since 'struct { ... }' is a valid type specifier |
| 03:30:08 | <Elly> | in any case |
| 03:30:16 | <Elly> | C is the only language I feel like I understand to that extent |
| 03:30:21 | <Elly> | I want to understand a better language that well :P |
| 03:30:33 | <hatds> | learn Haskell |
| 03:30:47 | <Elly> | that's why I was asking for something big to do in haskell before |
| 03:30:55 | <monochrom> | Whatever method you used to know C so well, use the same method on the better language. |
| 03:31:12 | <Elly> | the method I used to learn C was having to write a lot of stuff in C for classes and for work |
| 03:32:28 | <monochrom> | Hmm how did you know 2["heya"]? I imagine not from any project you did. Few people write it, and you wouldn't conceive it yourself --- I mean very unlikely. |
| 03:32:44 | <Elly> | oh, that I think I know from K&R |
| 03:32:49 | <Elly> | which I basically inhaled at one point |
| 03:32:54 | <solrize> | i think it is well known and obvious from the definition of [] |
| 03:33:04 | <Elly> | it's straightforward when you know that a[b] is a + b |
| 03:33:31 | <hatds> | you should be inhaling everything out there about haskell |
| 03:33:45 | <hatds> | that's what I did 24/7 for like a month in the fall |
| 03:33:45 | <monochrom> | OK, then that means to duplicate the same level of knowing Haskell, you should inhale the Haskell98 Report too. |
| 03:33:48 | <Elly> | hm |
| 03:34:12 | <rzezeski> | ACTION is slowly nibbling on RWH, taking copious amounts of notes |
| 03:34:31 | <hatds> | the haskell report is a breeze compared to C gotchas imho |
| 03:34:44 | <monochrom> | Indeed I inhaled some part of it, and so I can tell you with 100% certainty what "newtype" means and what it doesn't mean. |
| 03:34:58 | <hatds> | but you can't just learn the gotchas for haskell to really be feel like you understand it |
| 03:36:09 | <monochrom> | I also inhaled some of Bird's "introduction to functional programming using haskell, 2ed" and so I know the foldl vs foldl' business. |
| 03:36:32 | <Elly> | hm |
| 03:36:37 | <Elly> | so Haskell 98, it seems |
| 03:36:47 | <hatds> | there so many papers to read too if you are into type system stuff |
| 03:36:48 | <monochrom> | (P.S. If you what to know, kfish's 東京 means Tokyo.) |
| 03:36:59 | <Elly> | I am, in fact, into type system stuff :) |
| 03:37:13 | <Elly> | I learned intuitionistic logic a little while ago and I rather like it |
| 03:37:57 | <hatds> | how much do you feel you know about haskell? |
| 03:38:23 | <Elly> | not a lot |
| 03:38:29 | <Elly> | I know SML far better than I know Haskell |
| 03:39:47 | <hatds> | are you past the tutorial stage or not yet? |
| 03:40:19 | <Elly> | well |
| 03:40:40 | <Elly> | I understand recursion and things like fold quite well, I think |
| 03:40:50 | <Elly> | I have never seriously tried to grasp monads |
| 03:41:08 | <hatds> | do you grasp IO? |
| 03:41:37 | <Elly> | I understand monads as sequencers for explicit effects |
| 03:41:50 | <Elly> | (we had that presented as an application of lax modalities in intuitionistic logic) |
| 03:42:16 | <solrize> | do you understand how the State monad works? |
| 03:42:19 | <hatds> | can you write a simple haskell program asking for input in the form of text and numbers and outputing back some strings? |
| 03:42:39 | <Elly> | I could if I looked at the reference manual, I think |
| 03:42:51 | <hatds> | you need to do it I think |
| 03:43:01 | <Elly> | solrize: I understand the concept of passing a "heap" object and of the monad concealing that from you |
| 03:43:09 | <Elly> | solrize: but that is the extent of my understanding of State |
| 03:43:27 | <pao> | what's the preferred way to provide Word8 literals? |
| 03:43:46 | <dolio> | > 15 :: Word8 |
| 03:43:48 | <lambdabot> | 15 |
| 03:44:04 | <pao> | > fromEnum '\n' :: Word8 |
| 03:44:05 | <lambdabot> | Couldn't match expected type `Word8' against inferred type `Int' |
| 03:44:15 | <solrize> | elly the idea of State is that the actions in it are just a bunch of nested function calls |
| 03:44:29 | <Elly> | yeah; I think I understand the monads-as-CPS-transformers concept |
| 03:44:30 | <pao> | dolio: what if I wanted to "convert" a Char? |
| 03:44:51 | <monochrom> | > fromIntegral (fromEnum '\n') :: Word8 |
| 03:44:52 | <lambdabot> | 10 |
| 03:45:00 | <hatds> | well my opinion is this: you need to do basic "write this" tutorials that get you down and dirty with the syntax and type system. |
| 03:45:01 | <pao> | monochrom: thanks |
| 03:45:06 | <Elly> | hatds: alright |
| 03:45:11 | <monochrom> | fromIntegral is your all-purpose number converter. |
| 03:45:20 | <Elly> | ACTION goes off to write a program to take a string and print its length |
| 03:45:26 | <solrize> | > fromEnum '\n' |
| 03:45:27 | <lambdabot> | 10 |
| 03:45:35 | <solrize> | > :t fromEnum '\n' |
| 03:45:36 | <lambdabot> | <no location info>: parse error on input `:' |
| 03:45:40 | <monochrom> | fromEnum gives you Int |
| 03:45:58 | <pao> | monochrom: ... and with realToFract the toolbox is ready ... :-) |
| 03:46:04 | <mauke> | main = interact (unlines . map (show . length) . lines) |
| 03:49:28 | <soiamso> | Char in ghc is a unicode char? Word8 safe? |
| 03:51:03 | <monochrom> | unicode. 8 bits are not enough. |
| 03:52:06 | <Gracenotes> | however, Word8 does equal C's unsigned char, at least on my machine >_> |
| 03:52:15 | <Gracenotes> | (32-bit) |
| 03:53:13 | <mauke> | you have 32-bit chars? |
| 03:54:04 | <Gracenotes> | I mean, 32-bit x86 |
| 03:54:07 | <monochrom> | No, he means he has 8-bit chars. The "(32-bit)" is about the computer not C. |
| 03:54:39 | <SamB> | x86_32, I think they call it these days ... |
| 03:54:55 | <SamB> | (in Linux sources, if nowhere else!) |
| 03:55:33 | <Gracenotes> | perhaps only to distinguish between it and x86-64, I guess |
| 03:56:08 | <SamB> | well, they used to call it i386, I think |
| 03:56:21 | <Saizan> | Word8 is a pointer to a closure, anyhow |
| 03:56:23 | <SamB> | but then they merged it with the x86_64 code into one x86/ tree |
| 03:57:06 | <Elly> | that was surprisingly difficult to get right |
| 03:57:12 | <Elly> | and it is not as short as it ought to be |
| 03:57:19 | <SamB> | I know this because I'm in the process of documenting vm86(2) |
| 03:57:29 | <Elly> | SamB: my sympathies |
| 03:57:47 | <Elly> | that syscall and modify_ldt(2) both worry me deeply :P |
| 03:57:47 | <SamB> | you know something about vm86(2) ? |
| 03:58:28 | <Elly> | not in particular, but you're documenting a part of the linux kernel that touches something x86-specific |
| 03:58:44 | <SamB> | modify_ldt seems to be documented in much closer to the appropriate depth, as far as I can see |
| 03:58:54 | <SamB> | I mean, it's a much simpler call |
| 03:59:06 | <Elly> | they document two of the four legal values for func, at least :) |
| 04:00:24 | <SamB> | modify_ldt can work on x86_64 without crazy hacks, too, right? |
| 04:00:51 | <Elly> | um... I don't think it's necessary on x86_64, since most of the segments no longer exist |
| 04:00:57 | <Elly> | maybe it still is though |
| 04:01:17 | <Elly> | I know what modify_ldt does, but not the reason why it does it :P |
| 04:02:55 | <jesmon> | I'm trying to build package containers-0.2.0.1 (which is a dependency of yi-0.6) and it's failing because it can't find the module Data.Data |
| 04:03:07 | <jesmon> | but that module does seem to be on my system |
| 04:03:33 | <Elly> | is there a shorter way to write the following: |
| 04:03:34 | <Saizan> | jesmon: you need a more recent ghc |
| 04:03:43 | <Elly> | main = do x <- getLine; y <- return $ length x; putStrLn $ show y |
| 04:04:01 | <jesmon> | more recent than 6.10.1? |
| 04:04:45 | <monochrom> | main = do x<-getLine; let {y=length x}; putStrLn (show y) |
| 04:04:51 | <monochrom> | err |
| 04:04:56 | <monochrom> | main = do x<-getLine; let {y=length x}; print y |
| 04:05:07 | <Elly> | what's the let { ... } syntax? |
| 04:05:09 | <Saizan> | jesmon: ah, no |
| 04:05:22 | <monochrom> | If you use indentation, you will not need { } |
| 04:05:23 | <Saizan> | jesmon: then you've to pass --constraint="base >= 4" |
| 04:05:37 | <Saizan> | ACTION sighs |
| 04:05:42 | <Elly> | monochrom: why does the let make the return unnecessary? |
| 04:05:43 | <jesmon> | Saizan: I'll give it a try |
| 04:05:54 | <Saizan> | the core packages are the ones with more buggy .cabal files out there |
| 04:06:14 | <SamB> | Elly: last I got was: <Elly> maybe it still is though |
| 04:06:43 | <SamB> | then my mobo zonked out or something and the computer was rebooting ... |
| 04:06:50 | <SamB> | ACTION really needs to get that fixed :-( |
| 04:07:02 | <Elly> | SamB: I just said "I know what modify_ldt does but not why it exists" |
| 04:07:02 | <hatds> | Elly: you've heard of the explanation that IO (a) behaves like World -> (World,a) ? |
| 04:07:15 | <monochrom> | The do-notation supports "let". |
| 04:07:15 | <Elly> | hatds: yes, I am familiar with that idea |
| 04:07:19 | <jesmon> | Saizan: I got the same error, which is: |
| 04:07:42 | <SamB> | Elly: oh, DOSEMU uses it to emulate protected mode, and WINE to run 16-bit programs |
| 04:07:45 | <jesmon> | "Could not find module `Data.Data': it is a member of package base, which is hidden" |
| 04:07:49 | <hatds> | Elly: then the answer you want is essentially how do notation desugars into >>= and return |
| 04:07:51 | <SamB> | (also in protected mode) |
| 04:08:05 | <Elly> | hatds: sure, that would be good to know :) |
| 04:08:27 | <SamB> | Elly: well, truly it doesn't emulate protected mode, but just implements DPMI in a somewhat-unfriendly environment |
| 04:08:48 | <Elly> | x86 is by definition an unfriendly environment :) |
| 04:09:04 | <SamB> | I meant that it doesn't get to *touch* the IDT |
| 04:09:16 | <Elly> | ACTION nods |
| 04:09:23 | <Saizan> | jesmon: ok, unpack the package with cabal unpack, edit the .cabal file putting "base >= 4" in build-depends, and then run "cabal install" from there |
| 04:09:29 | <hatds> | Elly: http://www.haskell.org/tutorial/index.html under monads explains the desugar |
| 04:10:41 | <SamB> | Elly: and I think they can both do that on an x86_64 kernel just as well as on an x86_32 kernel -- not sure about either of them in a 64-bit userspace ... |
| 04:11:14 | <Elly> | thanks, hatds |
| 04:13:31 | <jesmon> | thanks, Saizan, the build succeeded :) |
| 04:16:09 | <Saizan> | jesmon: the reason is that cabal defaults to base-3 because many packages don't have an upper bound |
| 04:16:23 | <Saizan> | on base, in their build-depends |
| 04:16:43 | <Saizan> | but that works only if packages requiring base-4 have a lower bound |
| 04:16:56 | <Saizan> | ACTION badly wants a typechecker for packages |
| 04:17:24 | <jesmon> | hmm.. I'm having another problem, this time with building unix-2.3.2.0 |
| 04:17:43 | <Saizan> | unix-2.3.2 requires base-4.1 iirc |
| 04:17:47 | <Saizan> | and that comes with 6.10.2 |
| 04:18:10 | <jesmon> | looks like I need to upgrade then |
| 04:18:25 | <jesmon> | the error is: Module `GHC.Conc' does not export `Signal' |
| 04:18:31 | <Saizan> | yup |
| 04:18:53 | <Saizan> | yi explicitly depends on 2.3.2? |
| 04:19:16 | <jesmon> | looks like it to me... |
| 04:19:47 | <Saizan> | the cabal file doesn't specify a version |
| 04:20:15 | <Saizan> | btw, unix usually comes with ghc |
| 04:20:52 | <Saizan> | it doesn't have a version for containers either |
| 04:20:57 | <Saizan> | how are you isntalling yi? |
| 04:21:04 | <jesmon> | with cabal |
| 04:21:19 | <Saizan> | "cabal install yi"? |
| 04:21:43 | <jesmon> | cabal upgrade yi (from 0.5.2) |
| 04:22:20 | <Saizan> | ah! that's your problem |
| 04:22:25 | <Saizan> | use install |
| 04:22:42 | <Saizan> | upgrade tries to install the latest version of all the dependencies too |
| 04:23:03 | <Saizan> | which would work in a perfect world.. (discarding the ones you can't install on your system) |
| 04:23:16 | <Saizan> | but not in this one yet :) |
| 04:24:32 | <Asztal> | upgrade :: PerfectWorld -> (a, PerfectWorld)? |
| 04:24:54 | <SamB_XP> | Asztal: well, it would also sometimes work in imperfect worlds |
| 04:25:51 | <deech> | Hi all, I am trying to install the latest version of Haxml using cabal. cabal list the latest version as 1.19.7, but when I do a cabal install it downloads 1.13.3. I unregistered the HaXml package and deleted the cached package with the same results. |
| 04:26:32 | <tennin> | anyone familiar with staged type inference? |
| 04:26:58 | <SamB_XP> | tennin: do they use that in that meta-ML thingy ? |
| 04:27:09 | <tennin> | I think so |
| 04:27:35 | <tennin> | I'm trying to read the paper "dynamic typing as staged type inference" from 1999, but I can't seem to get a PS viewer installed on this windows computer |
| 04:28:07 | <SamB_XP> | tennin: try running ps2pdf over it ? |
| 04:30:07 | <jesmon> | Saizan: Bingo! "cabal install yi" successfully built and installed it. but I have this strange thing in ~/.yi/yi-x86_64-linux which is getting executed and which is still 0.5.2 |
| 04:30:12 | <monochrom> | install a virtual machine such as vmware or virtualbox. install linux inside it. install a PS viewer inside that. |
| 04:30:29 | <tennin> | =) |
| 04:30:33 | <jeffz`> | I've never had a problem with gs + gsview on Windows |
| 04:30:43 | <jesmon> | yi --version |
| 04:30:43 | <jesmon> | Launching custom yi: "/home/jesse/.yi/yi-x86_64-linux" |
| 04:30:43 | <jesmon> | yi 0.5.2 |
| 04:30:43 | <jesmon> | |
| 04:30:53 | <jesmon> | pardon |
| 04:33:15 | <Saizan> | jesmon: touch yi.hs , it should recompile yi-x86_64-linux on restart that way |
| 04:33:23 | <jesmon> | ok, just moving removing the "custom yi" worked |
| 04:33:53 | <tennin> | anyway, what I'm looking for is a better solution to the problem where I am dealing with some data that is a type that is only known at runtime, but is a definite type that will remain fixed after it's determined in some preliminary stage of processing |
| 04:33:53 | <jesmon> | yi --version then said "Recompiling custom yi" and reported the correct version |
| 04:34:15 | <tennin> | e.g. database schema, or even CSV header |
| 04:34:59 | <Saizan> | deech: 1.13.3 is the preferred version, if you want 1.19.x you've to ask for "HaXml >= 1.19" |
| 04:35:03 | <jesmon> | anyhoo, cabal is quite confusing to me so far :| |
| 04:35:14 | <tennin> | it seems to me that rather than foregoing all type safety because I don't know the type at compile-time, I should be able to use the typechecking machinery at runtime |
| 04:35:18 | <jesmon> | Saizan: thanks for all your help |
| 04:35:24 | <Saizan> | jesmon: np |
| 04:35:30 | <Saizan> | jesmon: there's a Cabal faq |
| 04:36:13 | <tennin> | thanks for the ps2pdf recommendation |
| 04:36:15 | <Saizan> | http://www.haskell.org/cabal/FAQ.html <- needs more entries, probably |
| 04:37:17 | <Saizan> | tennin: uhm, you can use gadts and/or existentials for that |
| 04:46:27 | <solrize> | ghc 6.10 introduces memory leaks into programs that didn't leak under 6.8.3??! |
| 04:48:28 | <jackdempsey> | hey guys, pretty basic q but feel like i'm missing something key |
| 04:48:34 | <tennin> | hmm, ok |
| 04:48:34 | <jackdempsey> | was looking at the definition of read |
| 04:48:46 | <jackdempsey> | and didn't get why 'a' was ambiguous |
| 04:48:50 | <jackdempsey> | then saw some other examples like |
| 04:48:53 | <jackdempsey> | rInt :: String -> Int |
| 04:48:53 | <jackdempsey> | rInt = read |
| 04:49:04 | <jackdempsey> | and i see whats going on, but maybe not why.... |
| 04:49:20 | <jackdempsey> | i mean, it looks like you're basically saying, read, i need back an int, go do your thing |
| 04:49:50 | <tennin> | Saizan: yeah, I think I can see the GADT approach |
| 04:50:02 | <jackdempsey> | so if you have a function foo :: String -> a |
| 04:50:16 | <jackdempsey> | you can then do things like bFoo :: String -> Bool |
| 04:50:21 | <jackdempsey> | bFoo = foo |
| 04:50:47 | <Jebdm> | jackdempsey: you can also use an inline type annotation |
| 04:50:49 | <jackdempsey> | not even sure how to google on this, hence me asking here :-) |
| 04:50:56 | <jackdempsey> | ok |
| 04:51:16 | <Jebdm> | ex. (read something :: Int) |
| 04:51:31 | <jackdempsey> | i see |
| 04:51:32 | <mauke> | the read thing works because we have return-type-based overloading |
| 04:51:37 | <jackdempsey> | ahh |
| 04:51:45 | <jackdempsey> | i think thats what i'm trying to grasp at |
| 04:52:08 | <jackdempsey> | i also didn't see how i was supposed to know from read :: String -> a that to call it i needed read "12"::Int |
| 04:52:16 | <jackdempsey> | but maybe thats not really important |
| 04:52:29 | <jackdempsey> | return-type-based overloading.....definitely haven't heard of that before |
| 04:52:32 | <Saizan> | it's read :: Read a => String -> a |
| 04:52:34 | <jackdempsey> | is that common in functional languages? |
| 04:52:40 | <mauke> | not really |
| 04:52:59 | <mauke> | I think most languages don't have typeclasses |
| 04:53:03 | <jackdempsey> | Saizan: yes definitely, thx for clarification. that should be enough to tell me about the ::Int part? |
| 04:53:06 | <hatds> | I love SPJ's spiel on return type overloading |
| 04:53:16 | <jackdempsey> | interesting |
| 04:53:52 | <Saizan> | jackdempsey: well, when a type variable has a typeclass constraint on it you need to choose a concrete type for it somehow |
| 04:54:07 | <Saizan> | jackdempsey: often just using the result in the rest of the code is enough |
| 04:54:15 | <jackdempsey> | ok |
| 04:56:57 | <jackdempsey> | k, possibly foot -> mouth here....but why is "Read a" in that definition capitalized? |
| 04:57:14 | <jackdempsey> | i'm used to some things capped because they're monads |
| 04:57:19 | <mauke> | heh |
| 04:57:24 | <jackdempsey> | modules |
| 04:57:24 | <jackdempsey> | hehe |
| 04:57:32 | <mauke> | in general, variables are lowercase and constants are uppercase |
| 04:57:44 | <mauke> | Int is a concrete type, a is a type variable |
| 04:58:00 | <mauke> | Read is the name of a class. I don't think we have class variables |
| 04:58:04 | <jackdempsey> | k, my terminology is sorely lacking, but i think i'm getting the ideas a little more each time i approach it |
| 04:58:07 | <hatds> | er not "constants" in the sense of values though |
| 04:58:09 | <jackdempsey> | ahh ok |
| 04:58:39 | <Gracenotes> | mmm. hot chocolate. ... in the summer. :\ |
| 04:58:50 | <jackdempsey> | mmm, bourbon :-D |
| 04:58:53 | <Gracenotes> | yum though |
| 04:59:00 | <mauke> | > let true = False in true |
| 04:59:02 | <lambdabot> | False |
| 05:09:47 | <deech> | Hi all, using Haxml, once a string is parsed into Haskell's XML representation, is there a way to lookup the attributes and content by tag |
| 05:41:11 | <Gracenotes> | mm. now it is time to see whether these wasabi peas are too hot for me or not. I suspect not. |
| 06:03:22 | <halberd> | has anybody tried to draw a link between types and statistical inference? |
| 06:04:50 | <halberd> | e.g., you give the line of best fit a type that says "this is the line of best fit for the data set D" |
| 06:05:25 | <halberd> | and how would that play out when your fit is only approximate, not exactly the best |
| 06:22:14 | <Lemonator> | I got a huge function, |
| 06:22:30 | <Lemonator> | but no segment of code inside is used twice. |
| 06:22:37 | <Lemonator> | Is it still worth it to break it up? |
| 06:25:20 | <cads> | hey, can reversible computing be implemented with conventional electronics? |
| 06:26:03 | <QtPlaty[HireMe]> | I've seen reversible computing implemented mechanitcally. |
| 06:27:05 | <cads> | what did it do? |
| 06:27:36 | <Saizan_> | Lemonator: yes, there are many reasons 1) you can test the subparts separately 2) with good names the overall logic becomes easier to read 3) you never know if/when you'd reuse something in the future |
| 06:28:17 | <Lemonator> | It seems like a pain in the ass to do, though. |
| 06:28:22 | <Lemonator> | behold: |
| 06:28:30 | <Saizan_> | don't paste here! |
| 06:28:33 | <copumpkin> | lol |
| 06:28:34 | <Saizan_> | @hpaste |
| 06:28:34 | <lambdabot> | Haskell pastebin: http://hpaste.org/new |
| 06:29:24 | <Lemonator> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4978#a4978 |
| 06:29:28 | <Lemonator> | what? |
| 06:31:50 | <copumpkin> | how would you test a function like that? |
| 06:31:52 | <Saizan_> | Lemonator: that looks like it could be written with less code, actually |
| 06:32:39 | <Lemonator> | oh? |
| 06:33:19 | <copumpkin> | a 5-tuple :o |
| 06:33:41 | <Saizan_> | instead of calling parse multiple times you could define a datatype like data Result = Ping .. | NewTopic .. | Message .. |
| 06:33:44 | <Twey> | Ew, a pentuple |
| 06:34:08 | <copumpkin> | using a record-based type instead of those n-tuples might make updating specific parts of them easier |
| 06:34:56 | <Lemonator> | what kind of record-based type? |
| 06:35:04 | <copumpkin> | respond (s, n, i, r, t) |
| 06:35:09 | <Saizan_> | then result = Ping `fmap` ping <|> NewTopic `fmap` newTopic <|> Message `fmap` message |
| 06:35:18 | <copumpkin> | it looks like your parse function returns a pentuple |
| 06:35:24 | <Lemonator> | yeah |
| 06:35:34 | <copumpkin> | which could probably be a nice type with record accessors |
| 06:35:43 | <Saizan_> | and case parse result of Right r -> case r of Ping .. -> ..; NewTopic .. -> ..; .. |
| 06:35:54 | <Saizan_> | parse result s, i meant |
| 06:36:36 | <Saizan_> | yeah, you could stick those in the Message constructor |
| 06:36:48 | <copumpkin> | it seems like you're using Right/Left as a kind of Maybe |
| 06:37:02 | <copumpkin> | you always ignore the Left |
| 06:37:05 | <copumpkin> | value |
| 06:37:15 | <copumpkin> | oh, I guess it's an error value? |
| 06:37:20 | <Lemonator> | well, parse returns an error value with Left, |
| 06:37:25 | <Lemonator> | and I really don't need it. |
| 06:37:48 | <copumpkin> | but yeah, doing it as Saizan said would get rid of a lot of that stuff |
| 06:37:54 | <Lemonator> | hm |
| 06:37:59 | <copumpkin> | since it's parser logic you're writing out by hand |
| 06:38:26 | <Saizan_> | if you're using parsec you might need to add "try" there |
| 06:41:42 | <SubStack> | blarg, updating a tree with multiple entrypoints into that tree is especially tricky |
| 06:42:36 | <SubStack> | since regular zippers are all about singlular active nodes |
| 06:42:43 | <SubStack> | from what I can tell |
| 06:42:54 | <copumpkin> | you could easily give it a constant number more |
| 06:43:45 | <SubStack> | and have the updates and insertions reflected in all of them? |
| 06:44:04 | <copumpkin> | oh, no |
| 06:44:07 | <copumpkin> | how do you mean? |
| 06:45:31 | <Saizan_> | oleg has "concurrent" zippers implemented with delimited continuations on its site |
| 06:46:33 | <SubStack> | I've come accross that page but I'll read it again |
| 06:47:51 | <SubStack> | hmmm I missed the push/pull idea before |
| 06:49:42 | <SubStack> | especially since the cursors will only sometimes actually need the updates |
| 07:21:58 | <_vikrant_> | sum |
| 07:22:07 | <juhp> | is http://code.haskell.org down? |
| 07:23:00 | <_vikrant_> | looks like |
| 07:23:14 | <_vikrant_> | me too... unable to open |
| 07:23:37 | <_vikrant_> | map |
| 07:23:55 | <_vikrant_> | :t map |
| 07:23:56 | <lambdabot> | forall a b. (a -> b) -> [a] -> [b] |
| 07:26:15 | <mathijs> | small question: I'm playing around with the FFI with help of RWH. this describes how to use c library functions from haskell. Is there some tutorial/info available on doing it the other way around? (using a haskell library from C)? |
| 07:26:37 | <mathijs> | or is this problematic because of the RTS needing to be loaded? |
| 07:27:10 | <Gracenotes> | iirc, two-way communication is possible |
| 07:27:48 | <mathijs> | ok, I hoped so, but I couldn't find a nice example of it. |
| 07:27:48 | <Gracenotes> | as far as I know Haskell "initiates" the communication with ccall declarations, though. |
| 07:28:29 | <Gracenotes> | I think the guide might be most useful: http://www.cse.unsw.edu.au/~chak/haskell/ffi/ |
| 07:28:36 | <Gracenotes> | or other guides, if any exist. hm... |
| 07:29:05 | <Gracenotes> | these are some blog articles, anyway. http://www.haskell.org/haskellwiki/Blog_articles/FFI |
| 07:29:11 | <Gracenotes> | not sure if they contain this info. |
| 07:29:16 | <mathijs> | ok, so if haskell initiates everything, it has to be the main binary right? I would like to just have some header file and .o object file to link against |
| 07:30:56 | <Gracenotes> | the first guide is, rather, the spec |
| 07:31:35 | <mathijs> | yeah I figured :) I'm not good at specs, ofcourse I can read them and find the info I need in the end, but I prefer a more basic example :) |
| 07:32:12 | <Gracenotes> | .nod. |
| 07:32:31 | <mathijs> | anyway, thanks for helping. I'll dig through it :) |
| 07:52:43 | <copumpkin> | Heffalump: I managed to get a free account with ARM :D |
| 07:56:41 | <myname> | exit |
| 08:15:40 | <hydo> | Looking at http://snurl.com/i922z , that's just crazypants use of . and not some sort of objective haskell mutant syntax, right? |
| 08:17:20 | <copumpkin> | > let f = \n m -> length . concat . (replicateM n >=> replicateM m) $ [undefined] in f 5 6 |
| 08:17:22 | <lambdabot> | 93750 |
| 08:17:24 | <opqdonut> | hydo: well the first . is looking up a name from the S namespace |
| 08:17:26 | <copumpkin> | > let f = \n m -> length . concat . (replicateM n >=> replicateM m) $ [undefined] in f 6 6 |
| 08:17:28 | <lambdabot> | 279936 |
| 08:17:31 | <opqdonut> | the second is just normal composition |
| 08:17:42 | <copumpkin> | > let f = \n m -> length . concat . (replicateM n >=> replicateM m) $ [undefined] in f 6 7 |
| 08:17:44 | <lambdabot> | 1959552 |
| 08:17:57 | <copumpkin> | that's pretty fast growth |
| 08:18:36 | <hydo> | copumpkin: right... it's just the same old . that I've come to know and love... just making sure. I've had to work with ruby lately so it was a bit of a shock to see it used that way at first. Just making sure that the world is still round, the sky is up, etc. |
| 08:18:46 | <copumpkin> | ? |
| 08:18:54 | <hydo> | oops |
| 08:19:02 | <copumpkin> | oh :) |
| 08:19:17 | <hydo> | s/ copumpkin / opqdonut / :) |
| 08:19:29 | <opqdonut> | :) |
| 08:19:47 | <Apocalisp> | irc is hard |
| 08:19:49 | <opqdonut> | the letters are like right nexto to eachother |
| 08:20:03 | <opqdonut> | -o |
| 08:50:45 | <fasta> | Why can't cabal simply work? Or, please give me a reason to still use cabal install... http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4980#a4980 |
| 08:53:14 | <opqdonut> | hehe |
| 08:53:58 | <wjt> | what notation for versioned dependencies does the cabal that shipped with ghc 6.8 support? i want to explicitly depend on base 3, but apparently the bundled cabal in ghc 6.8 chokes on 'base == 3.* ' |
| 08:56:15 | <Axman6> | hmm, so i'm reading http://www.cs.umd.edu/~avik/projects/cmllch/... does anyone understand what Concurrent ML does that's so special? i can't seem to understand what's actually happening, or why you would do it/want to |
| 08:59:02 | <quicksilver> | wjt: try base < 4 ? |
| 08:59:16 | <fasta> | Axman6: Didn't they have rendez-vous concurrency? |
| 08:59:23 | <pejo> | Axman6, Concurrent ML is rather old, and as you've figured out based on ML. |
| 08:59:37 | <fasta> | Axman6: I never used it, but Scheme 48 copied it, AFAIK. |
| 09:00:09 | <wjt> | quicksilver: lessee... |
| 09:00:28 | <Axman6> | either of you have a (hopefully not too long) explanation of what it's supposed to do? like how you'd use/what it does when used? |
| 09:00:50 | <wjt> | ACTION roundtrips to the bug reporter... |
| 09:05:04 | <pejo> | Axman6, CML extends SML with synchronous message passing (typed channels). CML has been around since atleast 1991, so it's probably older than any message passing toolkits for Haskell. |
| 09:05:27 | <xenoblitz> | Hi people, some a simple question: Does anyone know of a document which compares Phantom types and GADTs? |
| 09:05:35 | <xenoblitz> | * remove some |
| 09:05:46 | <ejt> | does anyone have an alternative link for Simons 'Fun with Type Functions' paper, microsofts seem to be having trouble with their webserver ? |
| 09:06:50 | <xenoblitz> | ejt: I managed to download hit here :/ |
| 09:06:56 | <xenoblitz> | *it |
| 09:07:16 | <ejt> | xenoblitz: I've been trying for the last hour, no luck |
| 09:07:39 | <ejt> | and there's a comment on reddit from a couple of days ago saying the website is donw |
| 09:07:45 | <ejt> | s/donw/down/ |
| 09:08:09 | <xenoblitz> | ejt: this one right? http://haskell.org/haskellwiki/Simonpj/Talk:FunWithTypeFuns |
| 09:08:20 | <ejt> | y |
| 09:08:56 | <xenoblitz> | weird I clicked the link and it downloaded :S |
| 09:09:00 | <quicksilver> | xenoblitz: it would be strange to compare them. |
| 09:09:01 | <ejt> | oh |
| 09:09:03 | <quicksilver> | xenoblitz: they are isomorphic. |
| 09:09:08 | <quicksilver> | xenoblitz: erm. wrong word. |
| 09:09:11 | <quicksilver> | xenoblitz: they are orthogonal! |
| 09:09:23 | <quicksilver> | xenoblitz: you can use phantom types and gadts separately, you can use them together |
| 09:09:34 | <quicksilver> | they're not alternatives. |
| 09:09:40 | <xenoblitz> | quicksilver: so you are basically saying they are used for different things? |
| 09:10:04 | <xenoblitz> | quicksilver: unfortunately I don't know what orthogonal means :( |
| 09:10:19 | <xenoblitz> | ejt: want me to email it to you somehow? |
| 09:10:26 | <ray> | at right angles |
| 09:11:03 | <xenoblitz> | ray: so different areas of applications? |
| 09:11:53 | <quicksilver> | xenoblitz: it means more or less what I followed up by saying. |
| 09:12:00 | <quicksilver> | They are independent - you can use one or the other or both. |
| 09:12:13 | <quicksilver> | I'm not sure how you'd compare & contrast them |
| 09:12:56 | <quicksilver> | a phantom type is a type you use "only" for type checking, but don't expect to have real members. |
| 09:13:12 | <quicksilver> | a GADT is an extension to an ADT which lets your constructors be less than fully polymorphic. |
| 09:14:44 | <Workybob> | I hate object oriented programming |
| 09:14:58 | <Workybob> | to define this data type I need more Objective-C files than I need lines in Haskell >.< |
| 09:15:18 | <quicksilver> | haha. |
| 09:16:49 | <quicksilver> | Workybob: I'm contributing to a C++ project where the author splits his class hierarchy into class CFoo : class IFoo, where IFoo is a pure virtual interface class. It's quite a sensible way to get real abstraction into C++ but OMG! the boilerplate |
| 09:17:09 | <Workybob> | hehe |
| 09:18:06 | <ivanm> | quicksilver: lol |
| 09:18:41 | <quicksilver> | three files for each new data type - interface/foo.h, foo/foo.h and foo/foo.c++ |
| 09:18:51 | <quicksilver> | makes me want an IDE :) |
| 09:19:23 | <ivanm> | ACTION assumes the .c++ file actually contains the code |
| 09:19:35 | <xenoblitz> | quicksilver: thanks for your pointers :) somehow they clarified things a bit |
| 09:20:02 | <quicksilver> | xenoblitz: good :) |
| 09:27:33 | <ivanm> | http://downforeveryoneorjustme.com/code.haskell.org :( |
| 09:28:38 | <thoughtpolice> | ivanm: yeah, it's really annoying |
| 09:29:38 | <ivanm> | who runs that server? |
| 09:30:39 | <thoughtpolice> | i think it's run out of galois or something |
| 09:30:51 | <thoughtpolice> | couldn't be sure though |
| 09:32:21 | <ivanm> | http://haskell.org/haskellwiki/Haskell.org_domain |
| 09:32:31 | <ivanm> | doesn't say who runs it... |
| 09:33:24 | <ivanm> | "hosted commercially" |
| 09:33:29 | <ivanm> | http://www.haskell.org/pipermail/haskell-cafe/2008-January/038759.html |
| 09:33:40 | <ivanm> | methinks a new host is needed... |
| 09:34:58 | <ivanm> | IIRC, planet.h wasn't loading about 8 hours ago... |
| 09:35:02 | <ivanm> | and still isn't :( |
| 10:13:47 | <Xen0x> | Can someone explain the need for all the # signs in the GHC Prim.hs (libraries/GHC-prim/GHC/Prim.hs)? |
| 10:14:08 | <quicksilver> | "need" ? |
| 10:14:10 | <fasta> | Is there anyone here with inside knowledge on the xml package? There seems to be some weird choices in it. |
| 10:14:16 | <quicksilver> | they're a convenitoin, that's all, xenoblitz |
| 10:14:21 | <fasta> | Xen0x: it's for extra 1337 points. |
| 10:14:22 | <quicksilver> | Xen0, sorry. |
| 10:14:34 | <quicksilver> | they conventionally denote compiler internals or compiler primitives |
| 10:14:44 | <quicksilver> | which should not, for example, appear in public APis. |
| 10:14:48 | <fasta> | Xen0x: ____INTERNAL___ is old, # is the new thing. |
| 10:15:15 | <fasta> | Xen0x: or you know what quicksilver says, but I think by explanation is more fun. |
| 10:15:15 | <Xen0x> | Ahh ok. I thought it was some kind of compiler optimization or something :) |
| 10:15:22 | <Baughn> | Xen0x: Of course, some of them end up exported anyway, but if you see # you know it's too low-level to use |
| 10:16:16 | <Xen0x> | Ok. I just bummed into it, because i'm looking into the whole foreign pointer thing and especially the stablePointer |
| 10:28:42 | <fasta> | What should this do according to you? takeUntil isNothing [Nothing] |
| 10:29:28 | <Baughn> | I'd say.. return nothing. |
| 10:29:36 | <Peaker> | > takeUntil isNothing [Nothing] |
| 10:29:37 | <Baughn> | > takeUntil isNothing [Nothing] |
| 10:29:38 | <lambdabot> | Not in scope: `takeUntil' |
| 10:29:38 | <lambdabot> | Not in scope: `takeUntil' |
| 10:29:52 | <fasta> | Baughn: if by that you mean [], then I agree. |
| 10:29:53 | <Baughn> | > takeWhile (not.isNothing) [Nothing] |
| 10:29:53 | <lambdabot> | [] |
| 10:30:15 | <fasta> | Baughn: unfortunately, that's not what the people writing Gofer thought... |
| 10:30:23 | <Baughn> | fasta: Eh? |
| 10:30:33 | <fasta> | Baughn: http://hackage.haskell.org/packages/archive/gofer-prelude/2.30.2/doc/html/src/Prelude-Gofer.html#takeUntil |
| 10:30:46 | <Baughn> | Oh dear |
| 10:31:23 | <fasta> | They managed to define takeUntil as takeUntilAndIncludeTheElementForWhichTestTestSucceeds |
| 10:31:34 | <fasta> | The* |
| 10:31:46 | <fasta> | Most people think until means < |
| 10:31:49 | <fasta> | Not <= |
| 10:32:20 | <yitz> | Why do "magic hashes" parse at all? It seems according to the Report that the hash should begin a new lexeme. |
| 10:32:35 | <quicksilver> | yitz: it would. |
| 10:32:44 | <quicksilver> | yitz: that's why there is a MagicHash extension. |
| 10:32:53 | <doserj> | take n xs ++ drop n xs == xs, so I would suggest takeUntil p xs ++ dropWhile p xs == xs |
| 10:33:01 | <yitz> | kind of ugly actually |
| 10:33:12 | <quicksilver> | yitz: (this makes it impossible for haskell98 code to 'accidentally' use a foo# identifier, so they are safe) |
| 10:33:25 | <quicksilver> | I would compare it to the why LaTex uses illegal @-identifiers internally |
| 10:33:39 | <quicksilver> | and redefines the catcode of @ for internal files. |
| 10:33:40 | <doserj> | erm, |
| 10:33:51 | <doserj> | ignore me |
| 10:35:14 | <doserj> | takeUntil p = takeWhile (not.p) and takeWhile p xs ++ dropWhile p xs == xs |
| 10:38:21 | <povman> | Who here actually uses list comprehension syntax? |
| 10:38:49 | <horms> | i do sometimes - though i don't code that much haskell |
| 10:39:09 | <Baughn> | I just list /monad/ syntax on occasion; anything small enough to be a comprehension tends to end up not being one |
| 10:40:11 | <povman> | It seems a bit useless to me. |
| 10:40:51 | <Baughn> | It's convenient if you're coming to haskell from other languages with list comprehensions |
| 10:41:07 | <Baughn> | And it's just a simplified version of monad syntax anyway. It doesn't get in the way. |
| 10:41:08 | <yitz> | povman: I use them all the time and I love them. |
| 10:41:52 | <quicksilver> | I find it occasionally convenient |
| 10:41:56 | <povman> | yitz: That's good to hear :D I feel bad about not using them (silly huh) |
| 10:42:02 | <yitz> | heheh |
| 10:42:11 | <quicksilver> | especially for what would in C be two nested looks |
| 10:42:20 | <Ferdirand> | sometimes I wish it would work on any MonadPlus, not just on lists |
| 10:42:35 | <quicksilver> | sequence_ [ drawPrettyThing a b | a <- [1..10], b <- [5,10..100] ] |
| 10:43:03 | <yitz> | They are really just a kind of specialized do notation that often (but not always) makes list monad expressions more human readable. |
| 10:43:17 | <yitz> | I like human readable code. |
| 10:44:57 | <quicksilver> | Ferdirand: I don't believe the desugaring of list comps ever uses (++) or mplus - no MonadPlus required? |
| 10:45:16 | <Ferdirand> | quicksilver: for conditions ? |
| 10:45:38 | <quicksilver> | oh, guard. |
| 10:45:46 | <quicksilver> | guard shouldn't be in MonadPlus, but it is, you're right. |
| 10:45:55 | <Saizan_> | MonadZero :) |
| 10:52:57 | <opqdonut> | hrmm, i do :back and get Exception: Prelude.undefined |
| 10:53:19 | <opqdonut> | the break was triggered by an undefined, and i can do one :back but the second fails |
| 10:54:43 | <opqdonut> | when i change the undefined into an error, :back works |
| 10:56:02 | <fasta> | dons: I am not sure whether loch was intended as a toy or not, but rewrite :: (TokenType,String) -> (TokenType,String) is too simplistic to work on real Haskell code. For toy examples it works fine, however. An example of something which does not work: export lists. |
| 10:57:39 | <Peaker> | fasta: well, if takeUntil includes that last element, it is more useful than if it is just takeUntil = takeWhile . not |
| 10:58:22 | <fasta> | Peaker: it might be more useful, but it's not what the name says. |
| 10:58:46 | <Peaker> | fasta: what name would say that? |
| 10:58:51 | <fasta> | Peaker: I.e. "take" something _until_ some condition. Not until and also include that element. |
| 10:58:53 | <Peaker> | (reasonable name :-) |
| 10:59:17 | <fasta> | Peaker: it would probably be a horrible name, but that's besides the point. |
| 11:00:13 | <Peaker> | fasta: I agree the name kind-of-implies that the last element is not included, but it does not equivocally say so |
| 11:00:29 | <Peaker> | unequivocally, that is |
| 11:01:00 | <Peaker> | @unpl takeUntil = takeWhile . not |
| 11:01:00 | <lambdabot> | takeUntil c = takeWhile (not c) |
| 11:02:47 | <int-e> | @unpl ap const id |
| 11:02:48 | <lambdabot> | ((\ a _ -> a) >>= \ d -> (\ b -> b) >>= \ c -> return (d c)) |
| 11:09:14 | <jelly12gen> | @info show |
| 11:09:14 | <lambdabot> | show |
| 11:09:24 | <jelly12gen> | @show |
| 11:09:24 | <lambdabot> | "" |
| 11:12:52 | <mgsloan> | some #math people are dicks. I suppose it'd be bad to ask a totally unhaskell question here, even though there are some awesome math people here? |
| 11:14:02 | <quicksilver> | mgsloan: well, depends what it is. If it's a part of maths which is related to haskell like CPOs or categories, then they are sometimes discussed here |
| 11:14:14 | <quicksilver> | mgsloan: otherwise there is always #haskell-blah |
| 11:14:47 | <mgsloan> | yeah, true. Ah, good idea. I'm afraid it's related to number theory rather than modern algebra |
| 11:15:21 | <Peaker> | #haskell has 590 people, and #-blah has 64, though |
| 11:15:30 | <burp_> | @users |
| 11:15:31 | <lambdabot> | Maximum users seen in #haskell: 658, currently: 591 (89.8%), active: 14 (2.4%) |
| 11:15:33 | <Peaker> | mgsloan: are you talking about that TRWBN or what's his name? :) |
| 11:15:54 | <Peaker> | mgsloan: a friend told me that #mathematics (I think that was the name) is better than #math |
| 11:16:18 | <poucet> | alias |
| 11:16:56 | <mgsloan> | Peaker - Jafet, actually, but #math certainly has its collection of oddities |
| 11:17:07 | <Twey> | 12:16:56 *** #mathematics 40 This channel is for seminars. Go to #math for math help. |
| 11:20:41 | <ivanm> | mgsloan: IIRC, roconnor or Cale have given seminars in #mathematics before... |
| 11:20:53 | <ivanm> | s/mgsloan/Twey/ |
| 11:21:00 | <mgsloan> | yeah, I know Cale is a math guru |
| 11:21:12 | <mgsloan> | read his treatsie on the whole nullity thing haha |
| 11:21:28 | <Twey> | ivanm: Hmn, might be worth hanging around in there, then |
| 11:21:29 | <Peaker> | fasta: inspired by the last discussion, I wrote a little something that lets you: main = print . take (more 1 $ listPred (<3)) $ [1..10] -- results in [1,2,3] |
| 11:21:49 | <Peaker> | fasta: no need for the "more useful" takeUntil that way |
| 11:22:11 | <Peaker> | list split predicates: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4985#a4985 |
| 11:28:58 | <Peaker> | What interesting class instances can this have? http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4985#a4987 |
| 11:29:40 | <Peaker> | hmm.. ListPred is probably a bad name, because it specifically splits lists, not filters them, etc |
| 11:34:02 | <Peaker> | Maybe the Data.Split module should have something like this? Its nice to be able to apply transformations to a split (such as take-some-more, etc) |
| 11:34:48 | <Peaker> | it does mean that building the thing by which you split is separate from applying it (an extra function application to use splitters) but it allows for more interesting combinations of splitting |
| 11:36:06 | <Axman6> | Tip: Excel absolutely sucks for statistical analysis, even for basic things like linear regression |
| 11:36:22 | <Axman6> | resist the urge! |
| 11:36:49 | <Peaker> | Excel is nice for being a "live" functional language, even if a weak one with really bad numeric types |
| 11:37:34 | <Botje> | can Excel have bottom? |
| 11:37:45 | <Axman6> | it is bottom |
| 11:37:47 | <Axman6> | rock bottom |
| 11:37:51 | <Botje> | :) |
| 11:37:53 | <thomastc> | it can kiss mine |
| 11:38:04 | <yitz> | Peaker: ghci is also live. The advantage of Excel is that it gives you typesetting much more conveniently than, say Cairo, at the moment. |
| 11:38:08 | <Axman6> | as much as MATLAB is a pain, it does shit right! |
| 11:38:58 | <yitz> | Botje: as in Haskell, Excel has several forms of bottom. For example, there is this blue screen... |
| 11:39:10 | <thomastc> | there is also the flight simulator |
| 11:39:11 | <Peaker> | yitz: maybe "live" was the wrong word. Excel is nice for allowing you to update the code and automatically get all of the data-dependencies updated automatically |
| 11:39:15 | <thomastc> | which is its best feature |
| 11:39:32 | <thomastc> | and it also has a bottom |
| 11:40:00 | <Botje> | :] |
| 11:40:02 | <yitz> | Peaker, yeah, but you can do that in ghci also. |
| 11:40:35 | <Peaker> | yitz: how? |
| 11:43:00 | <yitz> | Peaker: you define functions in terms of other variables using let. if you redefine a variable, you then up arrow to the function you want the current value of and hit enter. |
| 11:45:16 | <Peaker> | yitz: that means you manually update the dependencies |
| 11:45:56 | <Peaker> | yitz: the interesting thing in Excel is that it finds all the dependencies automatically, updates them, and dependencies can be interesting charts too |
| 11:46:21 | <Peaker> | Ok, now I have: (take . more 1 . splitBy $ (<"haha")) ["arc", "hello", "world"] == ["arc","hello"] |
| 11:48:52 | <povman> | I have nested 'withXXXX'. This is not the first time that has happened. The code looks remarkably like do notation. |
| 11:49:43 | <povman> | http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2440#a2440 |
| 11:50:03 | <quicksilver> | yup. |
| 11:50:07 | <quicksilver> | common pattern. |
| 11:50:24 | <povman> | I keep getting a hunch that it's a monad of some sort but I don't think it is |
| 11:51:05 | <lilac> | povman: looks like a simple form of a continuation monad? |
| 11:51:32 | <lilac> | although i'd be concerned about the associativity of bind |
| 11:52:49 | <quicksilver> | @hoogle withArgs |
| 11:52:49 | <lambdabot> | System.Environment withArgs :: [String] -> IO a -> IO a |
| 11:53:06 | <MyCatVerbs> | lilac: bind's right-associative, and monad laws mean that the associativity of it doesn't actually matter, no? |
| 11:53:14 | <quicksilver> | it's like a delimited bind. |
| 11:53:29 | <quicksilver> | I'm not sure if it relates to a monad |
| 11:53:32 | <quicksilver> | except by analogy |
| 11:53:35 | <lilac> | MyCatVerbs: i meant, i'm not sure that the bind of this "monad" is associative |
| 11:54:14 | <povman> | also, return is hard to define (if not impossible) |
| 11:55:53 | <MyCatVerbs> | lilac: oh, I thought you meant (>>=). My bad. |
| 11:56:13 | <povman> | I once read that if I have something that is like a monad but isn't, then it might be an Arrow |
| 11:57:38 | <Peaker> | povman: I think its better to try to come up with your own combinators and then later see if they match some existing type-class |
| 11:57:55 | <povman> | ah, good idea |
| 11:59:02 | <Peaker> | povman: where's withArgs from? |
| 11:59:12 | <povman> | System.Environment |
| 11:59:25 | <povman> | @src withArgs |
| 11:59:26 | <lambdabot> | Source not found. You speak an infinite deal of nothing |
| 11:59:41 | <Peaker> | withArgs :: [String] -> IO a -> IO a ? |
| 11:59:51 | <Peaker> | @type System.IO.withArgs |
| 11:59:53 | <lambdabot> | Not in scope: `System.IO.withArgs' |
| 11:59:59 | <Peaker> | @type System.Environment.withArgs |
| 11:59:59 | <povman> | ah yeah, my paste totally doesn't compile |
| 12:00:01 | <lambdabot> | forall a. [String] -> IO a -> IO a |
| 12:03:01 | <povman> | and i completely didn't read the type of 'withArgs' before i used it |
| 12:06:20 | <Saizan_> | povman: for with* functions nested like that you can use the ContT IO monad to get do-notation |
| 12:06:21 | <lilac> | povman: withArgs temporarily /sets/ the args |
| 12:06:47 | <povman> | lilac: I realise this now :D |
| 12:06:57 | <lilac> | povman: you probably just want do { args <- getArgs; ... } |
| 12:07:16 | <povman> | lilac: I was getting carried away with the nesting |
| 12:07:28 | <povman> | lilac: and turned my getArgs into a withArgs |
| 12:07:31 | <Saizan_> | ?type ContT withFile "foo" ReadMode |
| 12:07:31 | <lambdabot> | Not in scope: `withFile' |
| 12:07:32 | <lambdabot> | Not in scope: data constructor `ReadMode' |
| 12:07:47 | <povman> | Saizan_: That's very interesting. I'll investigate |
| 12:08:26 | <Saizan_> | you then wrap the whole thing in "runContT return" |
| 12:08:41 | <povman> | oh of course!!! |
| 12:15:01 | <lilac> | @type do ss <- ContT (Foreign.withMany Foreign.C.withCString ["hello", "world"]); (n, xs) <- ContT $ Foreign.withArrayLen ss . curry; return $ ?c_main (toEnum n :: Foreign.C.CInt) xs |
| 12:15:02 | <lambdabot> | forall r a. (?c_main::Foreign.C.Types.CInt -> GHC.Ptr.Ptr Foreign.C.String.CString -> a) => ContT r IO a |
| 12:15:12 | <Peaker> | povman: I also tried creating a newtype to describe those "with"s and I get: |
| 12:15:13 | <Peaker> | newtype Bracket m i o = Bracket { unBracket :: (i -> m o) -> m o } |
| 12:15:13 | <Peaker> | combine :: Monad m => Bracket m i1 o1 -> Bracket m i2 o2 -> Bracket m (i1, i2) (o1, o2) |
| 12:15:36 | <Peaker> | povman: so it might also be seen as a kind of arrow, maybe |
| 12:16:48 | <lilac> | @type flip runContT return $ do ss <- ContT (Foreign.withMany Foreign.C.withCString ["hello", "world"]); (n, xs) <- ContT $ Foreign.withArrayLen ss . curry; return $ ?c_main (toEnum n :: Foreign.C.CInt) xs |
| 12:16:50 | <lambdabot> | forall a. (?c_main::Foreign.C.Types.CInt -> GHC.Ptr.Ptr Foreign.C.String.CString -> a) => IO a |
| 12:17:11 | <lilac> | that look about right? |
| 12:18:50 | <povman> | All those ContT make my eyes fall out |
| 12:20:01 | <povman> | what the |
| 12:20:13 | <Peaker> | @type map ?f |
| 12:20:15 | <lambdabot> | forall a b. (?f::a -> b) => [a] -> [b] |
| 12:20:17 | <povman> | @t (+1) >>> (*2) |
| 12:20:18 | <lambdabot> | Maybe you meant: tell thank you thanks thx ticker time todo todo-add todo-delete topic-cons topic-init topic-null topic-snoc topic-tail topic-tell type . ? @ ft v |
| 12:20:33 | <povman> | @type (+1) >>> (*2) |
| 12:20:35 | <lambdabot> | forall b. (Num b) => b -> b |
| 12:20:50 | <povman> | ((+1) >>> (*2)) 3 |
| 12:20:57 | <povman> | > ((+1) >>> (*2)) 3 |
| 12:20:59 | <lambdabot> | 8 |
| 12:21:03 | <povman> | <3 |
| 12:22:00 | <Peaker> | how do implicit args work? how do you give them to functions? Don't they essentially add multi-arg functions to Haskell and ruin composability of functions? |
| 12:22:59 | <quicksilver> | they ruin everything. |
| 12:23:16 | <quicksilver> | let ?foo = 5 in {- expression including functions with implicit foo arg -} |
| 12:23:21 | <quicksilver> | is how you use them. |
| 12:28:30 | <Peaker> | @type filter isNull . map ?f |
| 12:28:32 | <lambdabot> | Not in scope: `isNull' |
| 12:28:35 | <Peaker> | @type filter null . map ?f |
| 12:28:37 | <lambdabot> | forall a a1. (?f::a1 -> [a]) => [a1] -> [[a]] |
| 12:28:47 | <Peaker> | quicksilver: seems like they're still composable |
| 12:29:28 | <Peaker> | @type (.) |
| 12:29:29 | <lambdabot> | forall b c a. (b -> c) -> (a -> b) -> a -> c |
| 12:29:33 | <qaz> | I've realized |
| 12:30:04 | <quicksilver> | Peaker: yes, you can still (.) compose them |
| 12:30:05 | <qaz> | it is dynamic languages that are restrictive, not static ones |
| 12:30:09 | <quicksilver> | Peaker: they don't ruin *everything* |
| 12:30:12 | <Peaker> | quicksilver: what compositions are destroyed? |
| 12:30:12 | <quicksilver> | Peaker: just, most things. |
| 12:30:37 | <quicksilver> | various natural code restructurings |
| 12:31:47 | <fasta> | How can I disable recursive expand for whatever is interpreting CPP? I thought the default was not to do recursively expand. |
| 12:32:12 | <Peaker> | quicksilver: sounds like they might be nice in the sense of having "keyword args"? |
| 12:32:37 | <Peaker> | though propagating them up automatically into random contexts where their names are meaningless is probably a bad idea |
| 12:34:51 | <Twey> | Peaker: There are better ways to get keyword arguments |
| 12:35:02 | <augustss_> | qaz: yes! :) |
| 12:35:08 | <Twey> | Oleg has a nice implementation |
| 12:35:46 | <fasta> | Twey: did you ever use his implementation? |
| 12:37:31 | <lilac> | Peaker: implicit args basically implicitly thread a reader monad through code which uses them |
| 12:38:00 | <povman> | qaz: I don't really understand that. Remember, there is no spoon! |
| 12:38:35 | <Peaker> | are they so much easier to implement than class aliases? |
| 12:38:37 | <lilac> | Peaker: viewing them as syntactic sugar for reader monads certainly helped me... |
| 12:39:11 | <boegel> | ACTION presses send on his large message to haskell-cafe, and wonders what will result from it |
| 12:39:15 | <lilac> | also, they're pretty similar to type class passing, in a vague way |
| 12:39:31 | <Peaker> | lilac: restriction accumulation on the type |
| 12:39:33 | <lilac> | (except more powerful since you can have multiple distinct and distinguishable instances) |
| 12:40:25 | <fasta> | boegel: maximum message size reached ;) |
| 12:40:29 | <lilac> | Peaker: i've failed to extract any semantics from that :-( |
| 12:41:48 | <Peaker> | lilac: composing two types that have restrictions results in a type that has the restrictions of both, but maybe that's not entirely accurate |
| 12:41:51 | <boegel> | fasta: eh? |
| 12:42:06 | <boegel> | fasta: oh |
| 12:42:09 | <fasta> | boegel: :) |
| 12:42:11 | <boegel> | fasta: well, might be close |
| 12:42:23 | <boegel> | fasta: has 9.7KB in attachments, and quite a bit of text |
| 12:42:57 | <boegel> | I hope some will take the time to read it |
| 12:45:15 | <povman> | Can I use cabal to generate and use the *_stub.? files used by FFI? |
| 12:45:40 | <povman> | cabal seems to like C being called from Haskell, but not the other way around :( |
| 13:02:16 | <kacper_> | how to proof reverse = rev ----- rev = aux [] where aux xs [] = xs aux xs (y:ys) = aux (y:xs) ys |
| 13:04:20 | <lilac> | @type let a = length ?foo; b = return 'x' `asTypeOf` ?foo in (let ?foo = mempty in ?foo, let ?foo = mempty in a `seq` ?foo, let ?foo = mempty in b `seq` ?foo, let ?foo = mempty in a `seq` b `seq` ?foo) |
| 13:04:20 | <EvilTerran> | kacper_, well, that depends on the definition of "reverse" |
| 13:04:21 | <lambdabot> | forall a a1 (m :: * -> *). (Monoid (m Char), Monoid a, Monad m) => (a, [a1], m Char, [Char]) |
| 13:04:41 | <lilac> | @src reverse |
| 13:04:42 | <lambdabot> | reverse = foldl (flip (:)) [] |
| 13:04:46 | <lilac> | kacper_: ^^ that reverse? |
| 13:05:05 | <EvilTerran> | kacper_, unless you mean "how to prove {rev = aux [] where aux xs [] = xs aux xs (y:ys) = aux (y:xs) ys} has the property {rev . rev = id}"? |
| 13:05:25 | <EvilTerran> | or whatever |
| 13:05:36 | <EvilTerran> | (insert other suitable properties as appropriate) |
| 13:05:50 | <EvilTerran> | (and note that one only works for finite lists) |
| 13:08:10 | <ivanm> | EvilTerran: only because if you want to reverse an infinite list, you'll be waiting for quite a while? :p |
| 13:09:10 | <EvilTerran> | ACTION supposes "rev . rev \refinesTo id" might be a better way of writing it |
| 13:09:28 | <EvilTerran> | although you'd probably want some kind of upper bound on the refinement, too |
| 13:11:53 | <ivanm> | with reads, why does it return a list? as a substitute for Maybe? |
| 13:12:37 | <EvilTerran> | ivanm, in case the parse is ambiguous, i believe |
| 13:12:52 | <ivanm> | EvilTerran: so it returns multiple possible parses? |
| 13:13:03 | <EvilTerran> | in theory, it can, yeah |
| 13:13:04 | <ivanm> | > reads "112" :: [(Int,String)] |
| 13:13:05 | <lambdabot> | [(112,"")] |
| 13:13:08 | <ivanm> | hmmm... |
| 13:13:09 | <EvilTerran> | although derived instances will never do that |
| 13:13:12 | <EvilTerran> | AFAIK |
| 13:13:14 | <ivanm> | can you think of an example? |
| 13:13:18 | <ivanm> | @src reads |
| 13:13:18 | <lambdabot> | reads = readsPrec minPrec |
| 13:13:25 | <ivanm> | @src readsPrec |
| 13:13:25 | <lambdabot> | Source not found. Where did you learn to type? |
| 13:13:30 | <ivanm> | @hoogle readsPrec |
| 13:13:30 | <lambdabot> | Prelude readsPrec :: Read a => Int -> ReadS a |
| 13:13:30 | <lambdabot> | Text.Read readsPrec :: Read a => Int -> ReadS a |
| 13:14:00 | <ivanm> | @src minPrec |
| 13:14:00 | <lambdabot> | Source not found. That's something I cannot allow to happen. |
| 13:14:02 | <EvilTerran> | because of the maximum munch meta-rule in the haskell grammar, derived instances will always be unambiguous |
| 13:14:23 | <ivanm> | derived as in "make one up"? or "deriving (Read)" ? |
| 13:14:28 | <Saizan> | but you can use `mplus` |
| 13:14:56 | <EvilTerran> | as in "deriving" |
| 13:14:57 | <ivanm> | Saizan: surely that came about after reads was implemented? |
| 13:15:01 | <ivanm> | EvilTerran: *nod* |
| 13:15:12 | <ivanm> | so it might be for custom types return multiple instances? |
| 13:15:42 | <Saizan> | ivanm: not sure, but i think the idea of using StateT [s] [] a as the simplest type for parsers is quite old |
| 13:15:48 | <EvilTerran> | for hand-written instances, the ambiguty might be useful, i guess. |
| 13:15:58 | <ivanm> | Saizan: *nod* |
| 13:16:30 | <EvilTerran> | ?unmtl StateT [s] [] a |
| 13:16:31 | <lambdabot> | [s] -> [(a, [s])] |
| 13:16:42 | <EvilTerran> | ?type reads |
| 13:16:43 | <lambdabot> | forall a. (Read a) => String -> [(a, String)] |
| 13:16:51 | <Peaker> | @src ReadS |
| 13:16:52 | <lambdabot> | Source not found. I've seen penguins that can type better than that. |
| 13:16:54 | <Peaker> | @info ReadS |
| 13:16:55 | <lambdabot> | ReadS |
| 13:17:07 | <ivanm> | heh |
| 13:17:11 | <EvilTerran> | @info \is -> "@undo" |
| 13:17:11 | <lambdabot> | \ is -> "@undo" |
| 13:17:23 | <Peaker> | @info sucks |
| 13:17:23 | <lambdabot> | sucks |
| 13:17:24 | <ivanm> | what a remarkably useful plugin... |
| 13:17:37 | <EvilTerran> | @info do x <- foo; y <- bar; return (x,y) |
| 13:17:38 | <lambdabot> | foo >>= \ x -> bar >>= \ y -> return (x, y) |
| 13:17:46 | <EvilTerran> | it's lambdabot's spelling correction at work :) |
| 13:18:25 | <EvilTerran> | ,src ''ReadS |
| 13:18:32 | <lunabot> | type ReadS a = String -> [(a, String)] |
| 13:18:51 | <Peaker> | Why '' ? |
| 13:18:53 | <ivanm> | so how is reads any different from applying ReadS? |
| 13:19:05 | <ivanm> | Peaker: that is the required magic voodoo incantation? |
| 13:19:08 | <ivanm> | *shrug* |
| 13:19:17 | <EvilTerran> | Peaker, ' quotes a value-level name, and '' a type-level name |
| 13:19:25 | <EvilTerran> | because that's how TH works |
| 13:19:25 | <ivanm> | EvilTerran: so what is @info turning into? @undo? |
| 13:19:38 | <EvilTerran> | ivanm, yeah, exactly |
| 13:19:40 | <Peaker> | EvilTerran: what do names without either ' or '' refer to? |
| 13:19:49 | <kacper_> | I found http://209.85.229.132/search?q=cache:JueXExHs2gEJ:www.haskell.org/soe/PPTSlides/Ch14.ppt+infinite+lists+haskell+induction&cd=6&hl=pl&ct=clnk&client=opera |
| 13:19:56 | <EvilTerran> | Peaker, er, the usual haskell meaning of the name? |
| 13:20:11 | <kacper_> | at the bootm is way to proof for infinite lists |
| 13:20:18 | <Peaker> | EvilTerran: meaning either value or type depending on context? |
| 13:20:55 | <EvilTerran> | Peaker, map is a function; 'map is its name |
| 13:22:00 | <ivanm> | EvilTerran: is that quoting in the same way lisps quote lists, etc.? |
| 13:22:13 | <EvilTerran> | , [$ty| map |] |
| 13:22:15 | <lunabot> | forall a b . (b -> a) -> [] b -> [] a |
| 13:22:18 | <EvilTerran> | , [$ty| 'map |] |
| 13:22:20 | <lunabot> | Name |
| 13:23:10 | <EvilTerran> | ivanm, it's related, yeah |
| 13:23:16 | <Peaker> | I hate TH syntax |
| 13:23:20 | <EvilTerran> | although it only applies to names, not arbitrary expressions |
| 13:23:33 | <EvilTerran> | ivanm, a closer analogy to (quote ...) would be [|...|] and friends |
| 13:23:53 | <ivanm> | and I (thankfully, methinks) have no idea what they do ;-) |
| 13:24:03 | <EvilTerran> | , [| 1 + 2 |] |
| 13:24:05 | <lunabot> | InfixE (Just (LitE (IntegerL 1))) (VarE +) (Just (LitE (IntegerL 2))) |
| 13:24:16 | <ivanm> | gah! |
| 13:24:34 | <ivanm> | is that expanding it out into it's behind-the-scenes representation? |
| 13:24:50 | <EvilTerran> | well, its TH-datatypes representation |
| 13:24:59 | <ivanm> | I take it the Maybe values are because you might not have values on either side of an operator? |
| 13:25:08 | <ivanm> | > [| (+2) |] |
| 13:25:08 | <lambdabot> | <no location info>: parse error on input `|' |
| 13:25:12 | <ivanm> | heh |
| 13:25:17 | <ivanm> | , [| (+2) |] |
| 13:25:19 | <lunabot> | InfixE Nothing (VarE +) (Just (LitE (IntegerL 2))) |
| 13:25:22 | <EvilTerran> | [|...|] is the syntax tree of (...) |
| 13:25:53 | <ivanm> | *nod* |
| 13:27:02 | <kacper_> | is filter f (xs++ys) = filter f xs ++ filter f ys for infinite lists? |
| 13:27:18 | <ivanm> | I would think so... |
| 13:27:25 | <ivanm> | why wouldn't it be? |
| 13:27:38 | <kacper_> | its only question |
| 13:28:08 | <mreh> | i've just been shown the hamming list in haskell |
| 13:28:26 | <kacper_> | and reverse xs = foldl ( flip(:) ) [] xs ? |
| 13:28:27 | <ivanm> | kacper_: I'm not trying to accuse your or anything |
| 13:28:35 | <ivanm> | @src reverse |
| 13:28:35 | <lambdabot> | reverse = foldl (flip (:)) [] |
| 13:28:48 | <mreh> | is the derivation of things such as circular definitions optimised |
| 13:29:02 | <mreh> | i've just answered my own question |
| 13:29:52 | <Peaker> | Will this be a circular structure: map id (cycle "hello") ? |
| 13:30:07 | <ivanm> | Peaker: internally you mean? |
| 13:30:09 | <mreh> | > let reverse xs = foldl (flip (:)) [] xs in reverse [1..10] |
| 13:30:10 | <Peaker> | yeah |
| 13:30:11 | <lambdabot> | [10,9,8,7,6,5,4,3,2,1] |
| 13:30:26 | <ivanm> | AFAIK, cycle doesn't have to return an infinite list, ghc just returns it that way... |
| 13:30:28 | <mreh> | @src reverse |
| 13:30:28 | <lambdabot> | reverse = foldl (flip (:)) [] |
| 13:30:38 | <Peaker> | ivanm: O(1) space |
| 13:30:45 | <ivanm> | Peaker: yeah |
| 13:30:47 | <Peaker> | or O(N) (N=cycle length) |
| 13:30:56 | <mreh> | :t flip |
| 13:30:57 | <lambdabot> | forall a b c. (a -> b -> c) -> b -> a -> c |
| 13:30:58 | <ivanm> | s/cycle/list/ |
| 13:31:21 | <ivanm> | Peaker: but IIRC, there's no haskellian reason for it to be circular |
| 13:31:36 | <Peaker> | ivanm: I guess I'm asking about ghc specifically |
| 13:31:44 | <mreh> | isn't cycle "hello" also a circular structure? |
| 13:31:49 | <Peaker> | I wonder if there's a good way to retain the nice space properties of cycle for functions of cycle too |
| 13:31:51 | <ivanm> | mreh: it is in ghc |
| 13:32:14 | <ivanm> | Peaker: is asking if map f . cycle also represented internally by ghc as a circular structure |
| 13:32:29 | <mreh> | let cycle x = x : cycle x in cycle "lo" |
| 13:32:35 | <mreh> | > let cycle x = x : cycle x in cycle "lo" |
| 13:32:37 | <lambdabot> | ["lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo"... |
| 13:32:54 | <Peaker> | that's repeat |
| 13:32:58 | <Peaker> | > repeat "lo" |
| 13:33:00 | <lambdabot> | ["lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo","lo"... |
| 13:33:11 | <mreh> | > let cycle x = concat ( x : cycle x in cycle "lo" ) |
| 13:33:12 | <lambdabot> | <no location info>: parse error on input `in' |
| 13:33:30 | <mreh> | > let cycle x = concat ( x : cycle "lo" ) in cycle "lo" |
| 13:33:31 | <lambdabot> | Couldn't match expected type `[Char]' against inferred type `Char' |
| 13:33:34 | <Peaker> | > let cycle xs = xs' ; xs' = xs ++ xs' in cycle "lo" |
| 13:33:35 | <lambdabot> | Not in scope: `xs' |
| 13:33:42 | <Peaker> | > let cycle xs = xs' where xs' = xs ++ xs' in cycle "lo" |
| 13:33:44 | <lambdabot> | "lololololololololololololololololololololololololololololololololololololo... |
| 13:33:47 | <mreh> | > let cycle x = concat ( x : cycle x ) in cycle "lo" |
| 13:33:48 | <lambdabot> | Occurs check: cannot construct the infinite type: a = [a] |
| 13:33:48 | <lambdabot> | Expect... |
| 13:33:55 | <yowgi> | @src cycle |
| 13:33:56 | <lambdabot> | cycle [] = undefined |
| 13:33:56 | <lambdabot> | cycle xs = xs' where xs' = xs ++ xs' |
| 13:34:17 | <mreh> | i didnt know there was an undefined keyword |
| 13:34:22 | <Peaker> | @src undefined |
| 13:34:23 | <lambdabot> | undefined = error "Prelude.undefined" |
| 13:34:23 | <mreh> | isn't error used for partial functions? |
| 13:34:27 | <mreh> | :D |
| 13:35:33 | <mreh> | my definition of cycle required an infinite list to be calculated |
| 13:35:38 | <mreh> | it wouldn't terminate |
| 13:35:56 | <mreh> | in fact, it's just plain wrong |
| 13:36:30 | <mreh> | i just did hamming lists, :(, my brane hurt |
| 13:36:44 | <mreh> | does anyone know the definition? |
| 13:37:15 | <Peaker> | mreh: its allowed to not terminate if it can generate some data constructors in finite time |
| 13:37:28 | <Jedai> | mreh: The definition of what ? |
| 13:37:42 | <mreh> | i take it that the circular defintion of the hamming list makes it a linear algorithm |
| 13:38:01 | <mreh> | if it were really recursive, it would take infinite time |
| 13:38:14 | <yairchu> | Jedai: Peaker gave the defintion you can guess the question now :) |
| 13:38:25 | <Peaker> | yairchu: hey! |
| 13:38:59 | <yairchu> | Peaker: Yoyo |
| 13:39:09 | <Peaker> | yairchu: you abandoned bigorilla? |
| 13:39:16 | <mreh> | @src merge |
| 13:39:16 | <lambdabot> | Source not found. I've seen penguins that can type better than that. |
| 13:39:20 | <mreh> | @src mer |
| 13:39:20 | <lambdabot> | Source not found. Where did you learn to type? |
| 13:39:38 | <yairchu> | Peaker: No I use it to sign lolcats |
| 13:39:41 | <Jedai> | @hoogle merge |
| 13:39:41 | <lambdabot> | Distribution.Simple.PackageIndex merge :: Package pkg => PackageIndex pkg -> PackageIndex pkg -> PackageIndex pkg |
| 13:39:41 | <lambdabot> | Text.Parsec.Error mergeError :: ParseError -> ParseError -> ParseError |
| 13:39:41 | <lambdabot> | Text.ParserCombinators.Parsec.Error mergeError :: ParseError -> ParseError -> ParseError |
| 13:39:55 | <mreh> | thanks |
| 13:40:02 | <Jedai> | mreh: If I remember correctly, merge was defined locally anyway |
| 13:40:18 | <Jedai> | mreh: You're talking about Hamming list, no ? |
| 13:40:20 | <mreh> | i'll paste some code in a sec, and you can explain to me how it works |
| 13:40:27 | <mreh> | Jedai: yes |
| 13:41:00 | <mreh> | i'm a little confused about how it works in linear time, but i am under the impression that it does work because it is represented as a circular structure |
| 13:41:36 | <Jedai> | mreh: it works the same way than "fibs = 0 : 1 : zipWith (+) fibs (tail fibs)", and no it's not circular at all |
| 13:41:54 | <Berengal> | The definition is circular... |
| 13:41:59 | <Berengal> | But that's not too unusual |
| 13:42:07 | <Jedai> | mreh: It's lazy |
| 13:42:09 | <mreh> | it doesn't recalculate the whole fibs |
| 13:42:20 | <mreh> | it just uses what it has already worked out in that definition above |
| 13:42:42 | <Jedai> | Berengal: circular in this sense right, but not in the same sense as the result of cycle is circular |
| 13:43:00 | <Berengal> | Jedai: No, indeed not |
| 13:43:02 | <mreh> | is that right? what I have just said? |
| 13:43:24 | <Jedai> | mreh: Right |
| 13:43:51 | <wli> | > let merge3 ~(x:xs) ~(y:ys) ~(z:zs) | x < y && x < z = x : merge3 xs (y:ys) (z:zs) | y < x && y < z = y : merge3 (x:xs) ys (z:zs) | z < x && z < y = z : merge3 (x:xs) (y:ys) zs | x == y && x < z = x : merge3 xs ys (z:zs) | x == z && x < y = x : merge3 xs (y:ys) zs | y == z && y < x = y : merge3 (x:xs) ys zs | otherwise = x : merge3 xs ys zs ; hams = 1 : merge3 (map (2*) hams) (map (3*) hams) (map (5*) hams) in take 10 $ drop 10 hams |
| 13:43:53 | <mreh> | so as it goes about it's evaluation, it saves alot of time |
| 13:43:53 | <lambdabot> | [15,16,18,20,24,25,27,30,32,36] |
| 13:44:31 | <mreh> | wli has got it |
| 13:44:55 | <mreh> | :t merge3 |
| 13:44:56 | <lambdabot> | Not in scope: `merge3' |
| 13:45:04 | <Jedai> | mreh: So hams is the same as fibs |
| 13:45:06 | <mreh> | does lambdabot not remember things |
| 13:45:20 | <wli> | @type let merge3 ~(x:xs) ~(y:ys) ~(z:zs) | x < y && x < z = x : merge3 xs (y:ys) (z:zs) | y < x && y < z = y : merge3 (x:xs) ys (z:zs) | z < x && z < y = z : merge3 (x:xs) (y:ys) zs | x == y && x < z = x : merge3 xs ys (z:zs) | x == z && x < y = x : merge3 xs (y:ys) zs | y == z && y < x = y : merge3 (x:xs) ys zs | otherwise = x : merge3 xs ys zs in merge3 |
| 13:45:21 | <lambdabot> | forall t. (Ord t) => [t] -> [t] -> [t] -> [t] |
| 13:45:31 | <mreh> | she's clever isnt h |
| 13:45:31 | <Peaker> | I dislike your function, wli :( |
| 13:45:32 | <mreh> | she |
| 13:45:37 | <Jedai> | mreh: merge3 was defined locally, it's not destined to be remembered |
| 13:45:39 | <wli> | Peaker: Why? |
| 13:45:48 | <mreh> | wli: just nest two merges |
| 13:45:54 | <Peaker> | wli: its repetative, there's probably a nicer way |
| 13:45:57 | <mreh> | merge one (merge two three) |
| 13:46:03 | <Jedai> | mreh: You can add a function to lambdabot with @let so that it will remember it |
| 13:46:15 | <Berengal> | mergeMany = foldl merge [] ? |
| 13:46:24 | <kacper_> | > reverse [1..] |
| 13:47:10 | <kacper_> | > reverse [1..] |
| 13:47:15 | <mreh> | what Berengal said |
| 13:47:32 | <Jedai> | kacper_: Could you stop asking impossible thing from lambdabot ? |
| 13:47:42 | <mreh> | haha |
| 13:47:59 | <mreh> | @faq Can Haskell reverse infinite lists? |
| 13:48:06 | <mreh> | she's thinking... |
| 13:48:08 | <lambdabot> | The answer is: Yes! Haskell can do that. |
| 13:48:35 | <Jedai> | mreh: Of course it takes infinite time and infinite memory but still... ^^ |
| 13:48:44 | <kacper_> | ;) |
| 13:49:33 | <Berengal> | > let merge [] ys = ys; merge xs [] = xs; merge (x:xs) (y:ys) = if x < y then x:merge xs (y:ys) else if x == y then x:merge xs ys else y:merge (x:xs) ys in foldl' merge [] [sort [1,5,4,6,7,4,5,6,7], sort [3,5,6,8,9,54,4,23,4,6,76,4,5,6,6], sort [5,6,3,4,6,78,8,6,4,5,6,6,78]] |
| 13:49:42 | <lambdabot> | [1,3,4,4,4,5,5,6,6,6,6,6,7,7,8,9,23,54,76,78,78] |
| 13:49:59 | <mreh> | if they are equal Berengal, you need to discard one |
| 13:50:10 | <mreh> | it's a speshul merge |
| 13:50:29 | <Berengal> | I thought I did... |
| 13:50:34 | <mreh> | yeah... |
| 13:50:35 | <mreh> | funny |
| 13:50:47 | <Berengal> | Ah, |
| 13:50:56 | <Berengal> | > let merge [] ys = ys; merge xs [] = xs; merge (x:xs) (y:ys) = if x < y then x:merge xs (y:ys) else if x == y then x:merge xs ys else y:merge (x:xs) ys in foldl' merge [] $ map nub [sort [1,5,4,6,7,4,5,6,7], sort [3,5,6,8,9,54,4,23,4,6,76,4,5,6,6], sort [5,6,3,4,6,78,8,6,4,5,6,6,78]] |
| 13:50:58 | <lambdabot> | [1,3,4,5,6,7,8,9,23,54,76,78] |
| 13:51:12 | <Berengal> | merge doesn't handle repeats in the same list well |
| 13:51:28 | <Berengal> | It requires sorted sets |
| 13:51:48 | <mreh> | why foldl' |
| 13:51:53 | <Berengal> | Why not? |
| 13:52:19 | <ahamay42> | To category experts: What is the difference between Haskell arrows and the morphisms of a category with Haskell types as Obejcts? |
| 13:52:42 | <ahamay42> | I always thought it's the same, but now I read it's something else |
| 13:57:09 | <hellige> | ahamay42: you mean haskell functions, or haskell arrows? |
| 13:57:42 | <mreh> | how can a brother make some dough fast with Haskell? |
| 13:58:03 | <lilac> | > let merge xs@(x:xt) ys@(y:yt) = case x `compare` y of { LT -> x:merge xt ys; EQ -> x:merge xt yt; GT -> y:merge xs yt }; merge xs ys = xs ++ ys in foldl' merge [] $ map (nub . sort) [[1,5,4,6,7,4,5,6,7],[3,5,6,8,9,54,4,23,4,6,76,4,5,6,6],[5,6,3,4,6,78,8,6,4,5,6,6,78]] |
| 13:58:04 | <lambdabot> | [1,3,4,5,6,7,8,9,23,54,76,78] |
| 13:58:46 | <lilac> | mreh: start with flour, butter, milk and yeast |
| 13:59:29 | <mreh> | Curry flavoured? |
| 13:59:49 | <ahamay42> | @hellige I mean arrows |
| 13:59:49 | <lambdabot> | Unknown command, try @list |
| 14:00:13 | <mreh> | any haskell game devs on? |
| 14:00:15 | <Elly> | we do not believe in your twitterisms here |
| 14:00:22 | <mreh> | i'm looking to get some experience |
| 14:00:42 | <hydo> | @Elly what's a twitterism? |
| 14:00:42 | <lambdabot> | Unknown command, try @list |
| 14:00:45 | <hydo> | (lawl) |
| 14:01:32 | <fasta> | mreh: you probably have more luck if you ask an actual question. |
| 14:02:10 | <mreh> | doesn anyone need any help on their haskell? :D |
| 14:02:24 | <hydo> | Why is it that you never realize that you aren't going to be funny until -after- you hit enter? |
| 14:02:56 | <mreh> | double negative |
| 14:03:07 | <hydo> | yep |
| 14:03:19 | <Twey> | I don't |
| 14:03:21 | <Twey> | :-P |
| 14:03:28 | <Berengal> | How is that a double negative? |
| 14:03:36 | <Elly> | sometimes double negatives are meaningfully distinct from positives, like in that case :P |
| 14:03:36 | <Twey> | Berengal: Never + aren't |
| 14:03:41 | <Twey> | Yeah |
| 14:03:42 | <hydo> | never ... aren't? or am I really more tired than I thought? |
| 14:03:48 | <Berengal> | Twey: They apply to two different things... |
| 14:03:52 | <opqdonut> | yeah |
| 14:03:53 | <Twey> | There's nothing logically wrong with that |
| 14:03:56 | <opqdonut> | never realize and are not |
| 14:04:02 | <Twey> | ACTION nods. |
| 14:04:03 | <povman> | Elly: non-negative is a prime example |
| 14:04:24 | <Elly> | povman: indeed :) |
| 14:04:35 | <Elly> | (if your definition of "negative" is "not positive or zero") |
| 14:04:37 | <mreh> | but if you un-negate (!) both of the negatives, you get a sentance that means something else |
| 14:04:45 | <hydo> | sentence |
| 14:04:46 | <hydo> | haw haw! |
| 14:04:50 | <hydo> | :) |
| 14:05:17 | <ahamay42> | I just stumbled across http://chris.chris-lotte.net/publications/2006/arrows/arrows.pdf and was wondering why Arrows should be such a complicated thing instead of just Morphisms |
| 14:05:55 | <mreh> | damn |
| 14:05:59 | <ahamay42> | and as I'm using Arrows in my master thesis, the answer is quite important to me :) |
| 14:07:19 | <opqdonut> | what do you mean by "such a complicated thing instead of just Morphism" |
| 14:08:31 | <mreh> | Does not compute |
| 14:10:04 | <mreh> | I can't stand half educated half wits like stephen fry and douglas adams whittering on about apple macs |
| 14:10:08 | <ahamay42> | opqdonut: well, they state "Hughes' arrow" corresponds to to monoids in a suitable subcategory etc." |
| 14:10:54 | <ahamay42> | but I always thought haskell arrows are just corresponding to the morphisms of a category |
| 14:11:08 | <ahamay42> | even it's a special one |
| 14:11:43 | <Saizan> | it's true that the class Arrow doesn't have a very good name |
| 14:12:01 | <Saizan> | it's a bit like taking only the first 100 primes and calling them Primes |
| 14:12:25 | <quicksilver> | they're something like morphisms in a CCC which admits a functor from Hask, aren't they? |
| 14:12:33 | <quicksilver> | (a CC-functor) |
| 14:13:04 | <ahamay42> | quicksilver: I'd agree |
| 14:13:24 | <lilac> | mreh: i think it's unfair to call stephen fry a half educated half wit, just because you disagree with his opinion... |
| 14:13:44 | <Saizan> | you should be able to write curry if that's true, right? |
| 14:14:03 | <Saizan> | and uncurry |
| 14:14:18 | <povman> | @seen Lemmih |
| 14:14:18 | <lambdabot> | Lemmih is in #haskell. I don't know when Lemmih last spoke. |
| 14:14:41 | <Saizan> | but a ~> (b ~> c) -> (a,b) ~> c needs ArrowApply i think |
| 14:14:59 | <quicksilver> | hmm, not CC-functors, then |
| 14:15:04 | <quicksilver> | just C-functors. |
| 14:15:13 | <quicksilver> | that is, they are required to preserve product but not apply |
| 14:15:23 | <quicksilver> | not sure why that particular setup was chosen as the default |
| 14:15:32 | <ahamay42> | so that means they are just the morphisms, but of a somewhat haskell-specific category? |
| 14:16:12 | <ahamay42> | I could live with that, I was just feeling bad to sell something to people as category which isn't, in fact :) |
| 14:16:25 | <Saizan> | each instance of Arrow creates a subcategory of Hask, i guess |
| 14:17:01 | <Saizan> | (and by "i guess" i mean, afaiu CT, which is not that much) |
| 14:17:34 | <hatds> | does every arrow instance have an identity? |
| 14:17:48 | <hatds> | arr id I guess :) |
| 14:17:56 | <Saizan> | where Hask is the category with types as objects and monomorphic functions as morphisms |
| 14:18:57 | <ahamay42> | why do they need to be monomorphic? |
| 14:19:52 | <hatds> | well, polymorphic functions are handled by treating them as natural transformations |
| 14:19:56 | <ahamay42> | hatds: exactly, but you have to give id explicitly when defining an Arrow instance as Arrow is a subclass of Category |
| 14:21:08 | <ahamay42> | ah you mean monomorphic in a sence that it's not polymorphic - I was thinking of injective functions |
| 14:21:35 | <hatds> | heh, no relationship between the two in this case |
| 14:21:56 | <ahamay42> | :) |
| 14:22:51 | <codebliss> | Does anyone see an error in my code? http://haskell.pastebin.com/mf33b59b |
| 14:23:04 | <codebliss> | I have the failed output in the pastebin, it's one I've never seen |
| 14:23:15 | <hatds> | then b -> then [b] |
| 14:23:25 | <codebliss> | Hm? |
| 14:23:41 | <hatds> | codebliss: line 3 |
| 14:23:43 | <ahamay42> | -> = replace by |
| 14:23:54 | <codebliss> | I'm expecting the following. clean [1,3,3,5,6,4,6,6,7] = [1,3,5,6,4,6,7] |
| 14:23:57 | <codebliss> | Alright |
| 14:24:10 | <codebliss> | Not nub, just two consecutive |
| 14:24:25 | <mreh> | easy |
| 14:24:26 | <hatds> | if the typechecker complains about constructing an infinite type with lists, then it is probably just a "single element list versus single element" mix up |
| 14:24:30 | <mreh> | oh... hang on |
| 14:24:32 | <mreh> | not easy |
| 14:24:41 | <codebliss> | Ah, alright |
| 14:25:12 | <TonyTheTiger> | hi guys, for one of my exercise tasks it asks us to write a function which combines a list of lists into a single list, concat' :: [[a]] -> [a] |
| 14:25:34 | <TonyTheTiger> | mreh: is that to me? |
| 14:25:46 | <mreh> | nup |
| 14:26:00 | <mreh> | that's an easy one |
| 14:26:03 | <Berengal> | concat' = concat :P |
| 14:26:12 | <mreh> | heehee |
| 14:26:13 | <Ferdirand> | concat' = join |
| 14:26:17 | <codebliss> | I gotta go to class in 5, anyone got any ideas? I'm missing something basic I assume |
| 14:26:21 | <TonyTheTiger> | Berengal: that defies the point of learning to do it myself |
| 14:26:27 | <Berengal> | Ferdirand: join = concat already |
| 14:26:36 | <mreh> | @src concat |
| 14:26:36 | <lambdabot> | concat = foldr (++) [] |
| 14:26:40 | <hatds> | boo |
| 14:26:48 | <ahamay42> | I guess you're supposed to write a recursive one |
| 14:26:51 | <Ferdirand> | Berengal: i know :) |
| 14:26:56 | <codebliss> | Points-Free = life |
| 14:26:57 | <TonyTheTiger> | yeah its a recursive task |
| 14:27:06 | <TonyTheTiger> | i tried a few things and its just error galore |
| 14:27:15 | <ahamay42> | then paste your attempts |
| 14:27:29 | <Saizan> | codebliss: use group |
| 14:27:43 | <Saizan> | > group [1,3,3,5,6,4,6,6,7] |
| 14:27:44 | <lambdabot> | [[1],[3,3],[5],[6],[4],[6,6],[7]] |
| 14:27:45 | <doserj> | codebliss, hint: the error is in the "then" branch here: clean (a:b:[]) = if a == b then b else a:b:[] |
| 14:27:54 | <codebliss> | I see, i already hoogled |
| 14:27:55 | <TonyTheTiger> | i tried concat' (x:xs) = concat' x ++ concat' xs but realised thats sooo wrong |
| 14:28:08 | <mreh> | just decompose a fold |
| 14:28:23 | <mreh> | fold is a generalisation of a recursive function application |
| 14:28:29 | <hatds> | the subexpression "concat' x" won't typecheck |
| 14:28:37 | <Berengal> | TonyTheTiger: concat' (x:xs) = x ++ concat' xs works |
| 14:28:39 | <Ferdirand> | but it's almost correct ! |
| 14:28:40 | <TonyTheTiger> | ahamay42: Although you can believe im lieying I work in one file which i kept deleting code, trial and error basis |
| 14:29:02 | <TonyTheTiger> | Berengal: I tried that but that gives an error |
| 14:29:08 | <mreh> | trial error gets you nowhere |
| 14:29:24 | <TonyTheTiger> | because x might be a list itself |
| 14:29:26 | <hatds> | trial error is good if you are thinking about your mistakes |
| 14:29:37 | <Berengal> | > let concat' [] = []; concat' (x:xs) = x ++ concat' xs in concat [[1..10],[11..20],[21..30]] |
| 14:29:38 | <lambdabot> | [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28... |
| 14:29:39 | <TonyTheTiger> | and the idea is to flatten the list from a [[a]] to [a] |
| 14:30:00 | <TonyTheTiger> | what the heck why does that work here |
| 14:30:07 | <TonyTheTiger> | gonna go test that again brb |
| 14:30:18 | <Berengal> | TonyTheTiger: x _is_ a list. You want to prepend it to the result of concating the rest of the list |
| 14:30:30 | <Berengal> | Remember, the input is of type [[a]] |
| 14:30:32 | <TonyTheTiger> | ahh but what if x isnt a list? |
| 14:30:34 | <TonyTheTiger> | then what? |
| 14:30:51 | <Berengal> | x has to be a list, because the input is of type [[a]] :P |
| 14:30:52 | <hatds> | ask yourself what's the type of concat' |
| 14:31:03 | <hatds> | ^^ that |
| 14:31:03 | <ahamay42> | the first element of a list of lists is a list :) |
| 14:31:09 | <Jedai> | TonyTheTiger: x is a elem of [[a]], it _has_ to be a list |
| 14:31:16 | <TonyTheTiger> | ooh ok thats where i screwed up |
| 14:31:22 | <codebliss> | let clean xs = map head $ group xs |
| 14:31:26 | <codebliss> | Thanks guys =) |
| 14:31:30 | <Berengal> | Yeah, nested types can get messy at first... |
| 14:31:35 | <TonyTheTiger> | i kept thinking a [[a]] could be [a,[]] |
| 14:31:54 | <ahamay42> | so it was good you stated your guess :) |
| 14:31:56 | <TonyTheTiger> | now it becomes easier |
| 14:32:09 | <ahamay42> | no, every element in a list needs to have the same type |
| 14:32:17 | <Jedai> | TonyTheTiger: Haskell is not Lisp |
| 14:32:22 | <TonyTheTiger> | ok so a list is a "type" then? |
| 14:32:28 | <Jedai> | TonyTheTiger: nor a dynamic language |
| 14:32:32 | <TonyTheTiger> | Jedai: I dont know about lisp :( |
| 14:32:51 | <ahamay42> | "a list of ..." is a type, like list of integers e.g. |
| 14:32:53 | <Jedai> | TonyTheTiger: [Int] is a type |
| 14:32:55 | <Berengal> | TonyTheTiger: A list is a type constructor |
| 14:33:01 | <Jedai> | TonyTheTiger: it's a list of Int |
| 14:33:03 | <Berengal> | That is, [] is a type constructor |
| 14:33:18 | <Jedai> | TonyTheTiger: [[Int]] is also a type, it's a list of lists of Int |
| 14:33:25 | <Berengal> | [] Int, or [Int] (they are the same), are lists of Ints |
| 14:33:41 | <TonyTheTiger> | ok so i cant have.... [[1,2,3],[1,2],5] but can have [[1,2],[3],[4,5]] |
| 14:33:44 | <Berengal> | Note that [] the value is an element of all lists |
| 14:33:56 | <Berengal> | > 3:[] |
| 14:33:57 | <lambdabot> | [3] |
| 14:33:59 | <Berengal> | > [3]:[] |
| 14:34:00 | <lambdabot> | [[3]] |
| 14:34:04 | <Jedai> | TonyTheTiger: Right, the list are homogenous (every element is of the same type) |
| 14:34:20 | <TonyTheTiger> | ok, thanks guys that really cleared that up |
| 14:34:38 | <TonyTheTiger> | i was thinking of various ways to validate if x was a list or a single element |
| 14:34:55 | <Berengal> | > concat [[[1],[2]],[[3],[4]]] |
| 14:34:56 | <lambdabot> | [[1],[2],[3],[4]] |
| 14:35:04 | <Jedai> | TonyTheTiger: That's not to say you can't do heterogenous lists (containing elements of miscellaneous types) in Haskell, but [] is not it |
| 14:35:51 | <Berengal> | > (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) (:[]) 5 |
| 14:35:52 | <lambdabot> | Couldn't match expected type `t1 |
| 14:35:57 | <Berengal> | :/ |
| 14:36:24 | <ahamay42> | I've got another categorial question: Hughes "generalizing monads to arrows" paper introduces a maybe functor - but I don't believe it really is a functor |
| 14:36:27 | <Jedai> | Berengal: forgot the (.) |
| 14:36:44 | <Berengal> | Jedai: Yeah, I sort of noticed... |
| 14:36:54 | <mreh> | desktop gaming is almost history, is there a haskell for web project? |
| 14:37:01 | <Jedai> | ahamay42: Why ? |
| 14:37:11 | <ahamay42> | I mean instead of A -f-> B, you now have A -f-> Maybe B |
| 14:38:07 | <ahamay42> | but when you have B -g-> C as well, then there's no clear mapping for the object B |
| 14:38:13 | <Jedai> | mreh: You mean a "Haskell on Rail" ? There are several, Happstack is probably one of the nicer and most complete (and most Haskellite) |
| 14:38:26 | <ahamay42> | as for f, B is mapped to B again |
| 14:38:39 | <ahamay42> | but for g, B is mapped to Maybe B |
| 14:38:39 | <adityam> | is there a higher order function that captures if (something) then [] else [a complicated list]? |
| 14:38:48 | <ahamay42> | I mean it the other way around |
| 14:39:01 | <ahamay42> | f and g swapped |
| 14:40:12 | <ahamay42> | so to make it a functor, I guess it should be like Maybe A -f-> Maybe B, analogueous to fmap in Haskell's Functor class |
| 14:40:23 | <Jedai> | adityam: guard ? |
| 14:40:37 | <quicksilver> | what are you talking ahamay42 ? :) Insufficient context. |
| 14:40:44 | <quicksilver> | A -> Maybe B is an arrow |
| 14:40:52 | <quicksilver> | it's the kleisli arrow of the maybe monad |
| 14:40:55 | <quicksilver> | is that what you mean? |
| 14:41:19 | <ahamay42> | not necessairy kleisli, but yes |
| 14:41:55 | <ahamay42> | I mean the idea is to have an arrow of type A -> B which in reality maps to an underlying arrow of type A -Y Maybe B |
| 14:42:21 | <quicksilver> | you're still not making sense. |
| 14:42:24 | <quicksilver> | (sorry) |
| 14:42:33 | <ahamay42> | no I am sorry :) |
| 14:42:40 | <quicksilver> | data MyArrow a b = a -> Maybe b |
| 14:42:45 | <quicksilver> | ^^ this is, indeed, an arrow |
| 14:42:51 | <quicksilver> | as it would be for any other monad instead of Maybe |
| 14:42:55 | <adityam> | Jedai: guard has a return type m (), I need a return [a] (or m a) |
| 14:43:02 | <quicksilver> | kleisli composition induces and arrow for all monads. |
| 14:43:08 | <endojelly> | hmm, so let me get synthesize in Data.Generics right... |
| 14:43:16 | <endojelly> | why is the following not working: |
| 14:43:20 | <endojelly> | linearizeStmt :: Code -> [Code] -> [Code] |
| 14:43:22 | <lilac> | ahamay42: Maybe is itself a functor. it maps the type X to the type Maybe X, and arrows (functions) X -> Y to arrows Maybe X -> Maybe Y |
| 14:43:33 | <endojelly> | oh wait a minute. |
| 14:43:39 | <ahamay42> | yeah but I'm not interested in Kleisli an Monads, just arrows in general |
| 14:43:40 | <hatds> | adityam: if/then/else |
| 14:43:43 | <ahamay42> | like in Hughes' paper |
| 14:43:52 | <lilac> | ahamay42: like all correct instances of the Functor typeclass, Maybe is a covariant endofunctor on Hask. |
| 14:43:58 | <Jedai> | adityam: guard False >> ['a'..'e'] |
| 14:44:02 | <endojelly> | no it doesn't work. |
| 14:44:03 | <endojelly> | so: |
| 14:44:04 | <Jedai> | > guard False >> ['a'..'e'] |
| 14:44:04 | <hatds> | adityam: or something like liftM3 if' |
| 14:44:05 | <lambdabot> | "" |
| 14:44:09 | <endojelly> | linearizeStmt :: Code -> [Code] -> [Code] |
| 14:44:12 | <Jedai> | > guard True >> ['a'..'e'] |
| 14:44:14 | <lambdabot> | "abcde" |
| 14:44:14 | <endojelly> | linearize code = synthesize [] (++) (mkQ [] linearizeStmt) |
| 14:44:24 | <endojelly> | that's obviously wrong |
| 14:44:26 | <endojelly> | but... hm, why? |
| 14:44:30 | <endojelly> | :t synthesize |
| 14:44:31 | <lambdabot> | forall s t a. (Data a) => s -> (t -> s -> s) -> GenericQ (s -> t) -> a -> t |
| 14:44:34 | <adityam> | hatds: I wan to avoid if then else because the if condition is empty |
| 14:44:51 | <endojelly> | so the third argument should be of type (Data a => a -> s -> t), no? |
| 14:44:56 | <adityam> | Jedai: Thanks |
| 14:44:57 | <endojelly> | s and t are the same for me, both [Code] |
| 14:44:59 | <hatds> | adityam: then a guard is not what you maybe |
| 14:45:05 | <hatds> | adityam: *not what you want |
| 14:45:06 | <ahamay42> | I'm talking about the Arrow class and functors in a categorial sense (not the functor class which is just for functions) |
| 14:45:07 | <Ferdirand> | adityam: filterM perhaps ? |
| 14:45:08 | <endojelly> | so it should have type a -> [Code] -> [Code] |
| 14:45:13 | <Jedai> | hatds: guard works perfectly |
| 14:45:38 | <endojelly> | wouldn't (mkQ [] linearizeStmt) result in a function of type a -> [Code] -> [Code], given a function of type Code -> [Code] -> [Code]? |
| 14:45:42 | <endojelly> | :t mkQ |
| 14:45:43 | <lambdabot> | forall r b a. (Typeable b, Typeable a) => r -> (b -> r) -> a -> r |
| 14:46:28 | <endojelly> | so, for me, that's [Code] -> (Code -> [Code] -> [Code]) -> a -> [Code] -> [Code], no? |
| 14:46:49 | <lilac> | > let f x = guard (x > 1) >> [0..x] in (f 0, f 1, f 2, f 3) |
| 14:46:50 | <lambdabot> | ([],[],[0,1,2],[0,1,2,3]) |
| 14:47:05 | <Jedai> | ahamay42: The functor class is not "just for function", it corresponds to a Functor in the CT sense |
| 14:47:06 | <ahamay42> | so to be more precise: My remark is about http://www.cs.chalmers.se/~rjmh/Papers/arrows.pdf page 26 |
| 14:47:31 | <ttmrichter> | Are there any GHC porting experts available at the moment? |
| 14:47:46 | <ahamay42> | Jedai, yes it does but still it is limited to inputs od type a -> b instead of (Arrow ar) => ar a b |
| 14:47:55 | <ahamay42> | *of |
| 14:48:34 | <lilac> | ahamay42: the Functor class is for covariant endofunctors on Hask. |
| 14:48:37 | <Jedai> | ahamay42: Ok, in that sense I agree, it's just restricted to a certain category (Hask) where arrows are functions |
| 14:48:47 | <ahamay42> | yes |
| 14:48:48 | <lilac> | the arrows of Hask are functions, so in that sense you're right :) |
| 14:49:41 | <ahamay42> | I was just wondering about Hughes' introducing his MaybeFunctor as (mathematical functor, which doesn't make sense to me |
| 14:50:05 | <ahamay42> | as I don't find a mapping between the two involved categories |
| 14:50:11 | <lilac> | ahamay42: every Functor instance is a (mathematical) functor, but the converse is not true |
| 14:50:55 | <ahamay42> | lilac: yes, I agree, but I'm absolutely not talking about the Functor class, so let's forget about this for now :) |
| 14:51:30 | <lilac> | sounds like i should read the paper in question then :-) |
| 14:51:55 | <Cale> | ahamay42: hmm... |
| 14:51:59 | <lilac> | from which category is Hughes' MaybeFunctor a functor? |
| 14:52:13 | <ahamay42> | I hoped someone here had already read this :) |
| 14:53:36 | <ahamay42> | he doesn't state, but I guess it must be a mapping between the category with a (an Arrow instance) as morphisms and the one with MaybeFunctor a as morphisms |
| 14:53:42 | <hatds> | ahamay42: MaybeFunctor is a functor on Hask |
| 14:53:50 | <ahamay42> | though I'm not sure about the direction |
| 14:53:55 | <Cale> | ahamay42: hmm... well, this is a functor in a number of ways, but not the obvious way you'd expect. |
| 14:54:21 | <ahamay42> | how can it be a functor in Hask if the definition is an generic arrows and not functions? |
| 14:54:54 | <ahamay42> | cale: sounds interesting :) |
| 14:56:07 | <Cale> | If you think of the collection, for all types b and c of arrows a b c as a category under <<< and arr id, then you'd normally expect a functor F to send each object t to an object F t, and an arrow a b c to an arrow a (F b) (F c). But that's not what this does. |
| 14:56:52 | <ahamay42> | yes, I can follow until here :) |
| 14:57:10 | <endojelly> | ooh, I got it. |
| 14:57:52 | <endojelly> | @hoogle a -> [a] |
| 14:57:52 | <lambdabot> | Prelude repeat :: a -> [a] |
| 14:57:53 | <lambdabot> | Data.List repeat :: a -> [a] |
| 14:57:53 | <lambdabot> | Prelude iterate :: (a -> a) -> a -> [a] |
| 14:58:07 | <endojelly> | come on, there's got to be a singleton function for lists |
| 14:58:13 | <Cale> | (:[]) |
| 14:58:21 | <doserj> | or return |
| 14:58:24 | <quicksilver> | fear the monkey. |
| 14:58:30 | <endojelly> | Cale, yes I know that one but that's not nice |
| 14:58:32 | <endojelly> | doserj, oooh. |
| 14:58:35 | <endojelly> | of course |
| 14:58:40 | <Cale> | endojelly: What's not nice about it? |
| 14:58:43 | <Jedai> | endojelly: You have pure too |
| 14:58:44 | <quicksilver> | how can you say the monkey isn't nice? |
| 14:58:50 | <quicksilver> | That's a pretty dangerous comment. |
| 14:58:59 | <Jedai> | > pure 5 :: [Int] |
| 14:59:00 | <lambdabot> | Ambiguous occurrence `pure' |
| 14:59:00 | <lambdabot> | It could refer to either `Control.Appl... |
| 14:59:04 | <quicksilver> | (:[ {- I've seen it eat young children whole -} ]) |
| 14:59:15 | <Jedai> | > Control.Applicative.pure 5 :: [Int] |
| 14:59:16 | <lambdabot> | [5] |
| 14:59:26 | <endojelly> | Cale, because just "singleton" would be nicer, instead of combining two constructors |
| 14:59:29 | <Cale> | There is at least one sense in which it is a functor: if c is any type, MaybeFunctor a b can be applied to it, and if f: c -> c' is any function, then we get a corresponding function MaybeFunctor a b c -> MaybeFunctor a b c' |
| 14:59:59 | <Cale> | endojelly: "singleton" is way more typing for less clarity about what it does ;) |
| 15:01:20 | <doserj> | I bet there is a singleton::Collection c e => e -> c e somewhere |
| 15:01:26 | <ahamay42> | Cale: that sounds reasonable - but do you think this is what Hughes meant when he called if fucntor instead of say arrow transformer? |
| 15:01:35 | <Cale> | ahamay42: I don't think so. |
| 15:01:44 | <hellige> | is there an easy way to build profiling-supporting libraries without rebuilding all of ghc? |
| 15:02:06 | <Cale> | ahamay42: oh, wait, I see |
| 15:02:15 | <hellige> | i need ghc6-prof for 6.10.1 on ubuntu, and there's no package for it. :( |
| 15:02:21 | <Cale> | ahamay42: It's a functor, but not an endofunctor. |
| 15:02:44 | <Jedai> | hellige: If you build GHC yourselve and didn't build profiling... I don't think so. On the other hand, the binary package comes with profiled libraries |
| 15:02:50 | <ahamay42> | between which categories? |
| 15:03:09 | <Cale> | ahamay42: It goes from the category Hask to the Kleisli category for Maybe |
| 15:03:27 | <Cale> | well... |
| 15:03:29 | <hellige> | Jedai: no, it doesn't... not on ubuntu... :( |
| 15:03:45 | <ahamay42> | okay, so you're still with the same functor |
| 15:03:47 | <hellige> | Jedai: someone build a 6.10.1 binary package, but the profiling support is separate. |
| 15:04:04 | <Cale> | The subcategory of Hask constructed by Hughes arrows a to ... |
| 15:04:04 | <hellige> | and no one built it yet, i guess. so if i want a binary package with profiling, i have to go back to 6.8.2. :( |
| 15:04:19 | <ahamay42> | maybe I should email him and ask whether this is what he meant :) |
| 15:04:22 | <Jedai> | hellige: I use the binary package from GHC webpage myself |
| 15:04:42 | <hellige> | Jedai: ah, yeah, forgot they had one. i'll give that a shot, maybe. thanks for the reminder. |
| 15:05:00 | <Jedai> | hellige: it contains profiled version of the libraries IIRC |
| 15:05:22 | <Cale> | Okay, I think I can formalise this in a way which probably agrees with him. |
| 15:05:31 | <Jedai> | hellige: Don't forget to configure your cabal to gets profiled version of the package you install with it |
| 15:06:15 | <hellige> | Jedai: yeah, i know i'll have to rebuild some cabal stuff. but that won't take too long. |
| 15:06:18 | <hellige> | Jedai: thanks! |
| 15:06:34 | <Cale> | Fix the Hughes arrow a, and let Hask_a be the category whose objects are the objects of Hask, and whose arrows f: b -> c are the values of type a b c, with composition <<< |
| 15:08:46 | <Cale> | Let Hask_a^Maybe be the category whose objects are the objects of Hask_a (which are the objects of Hask), and whose arrows f: b -> c are the arrows in Hask_a, f: b -> Maybe c, but then these are the values of type a b c in Hask |
| 15:08:54 | <Cale> | er |
| 15:09:02 | <Cale> | values of type a b (Maybe c) rather |
| 15:09:16 | <ahamay42> | Cale: sorry, I've got to leave now - are you still with c->c' to MaybeFunctor a b c -> MaybeFunctor a b c' ? Or some new start and target categories? |
| 15:09:24 | <Cale> | ahamay42: New ones |
| 15:09:41 | <Cale> | Then MaybeFunctor a is a functor Hask_a -> Hask_a^Maybe |
| 15:09:58 | <ahamay42> | yeah, but I don't believe it really is a functor |
| 15:10:05 | <Cale> | We can check :) |
| 15:10:09 | <ahamay42> | maybe we can finish this diskussion another time |
| 15:10:33 | <ahamay42> | or mail me to bsteuber@gmail.com - this would be great :) |
| 15:10:37 | <Cale> | liftMaybe is the actual functor |
| 15:10:44 | <ahamay42> | hm ok |
| 15:11:22 | <Cale> | MaybeFunctor implements the type level machinery for it, and liftMaybe actually transforms the arrows as needed |
| 15:12:16 | <Cale> | In any event, this is more or less just the Kleisli category embedding. Maybe is also a monad on the category Hask_a |
| 15:13:15 | <ahamay42> | ok thanks for your help - I'll think it over |
| 15:13:39 | <ahamay42> | I'll go now - bye |
| 15:15:58 | <Cale> | Amazing the amount of discussion that 3 lines of code can generate ;) |
| 15:17:40 | <endojelly> | I don't think I really "get" synthesize yet %) |
| 15:18:08 | <endojelly> | "2nd argument o is for reduction of results from subterms" |
| 15:21:34 | <Cale> | Which synthesize? |
| 15:21:52 | <endojelly> | Data.Generics.Synthesize |
| 15:21:57 | <Cale> | Sounds like something from Generic... yes |
| 15:24:17 | <Cale> | hmm |
| 15:24:21 | <Cale> | synthesize z o f x = f x (foldr o z (gmapQ (synthesize z o f) x)) |
| 15:25:32 | <Cale> | or... |
| 15:25:45 | <qaz_> | to delete from a BST do you really need 9 cases or should 3be enough? |
| 15:26:21 | <Cale> | qaz_: What does your BST type look like? |
| 15:28:04 | <endojelly> | nevermind. apparently, I want "everything" instead of "synthesize" anyway. |
| 15:28:19 | <qaz_> | Cale: data BinarySearchTree a = |
| 15:28:19 | <qaz_> | Leaf | Node a (BinarySearchTree a) (BinarySearchTree a) |
| 15:28:19 | <qaz_> | deriving(Show) |
| 15:28:34 | <Tobsan> | qaz_: three cases should be enough |
| 15:28:53 | <Cale> | I can't imagine what the 9 cases would even be ;) |
| 15:29:00 | <qaz_> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4992#a4992 |
| 15:29:03 | <qaz_> | ^^ those |
| 15:31:10 | <Tobsan> | meh |
| 15:31:13 | <qaz_> | 10 caes actually |
| 15:31:17 | <Tobsan> | oh |
| 15:32:17 | <Cale> | Let me give it a shot. |
| 15:33:12 | <gnuvince_> | @src ((->) a) mappend |
| 15:33:12 | <lambdabot> | Source not found. |
| 15:33:16 | <gnuvince_> | @src mappend ((->) a) |
| 15:33:16 | <lambdabot> | Source not found. That's something I cannot allow to happen. |
| 15:33:24 | <gnuvince_> | gah, I never can do this right |
| 15:33:52 | <quicksilver> | it's not a monoid, anyway. |
| 15:34:01 | <quicksilver> | it has the wrong kind - it still has a parameter. |
| 15:34:07 | <quicksilver> | Monoids have to have no parameter. |
| 15:34:36 | <quicksilver> | you could write a Monoid instance for Monoid m => Monoid (a -> m) but I don't think that's in the libs anywhere. |
| 15:34:43 | <MyCatVerbs> | I need a better model of GHC's type system. Some of the things it lets me get away with are just heinous, and yet at the same time relatively innocuous looking stuff fails. :) |
| 15:35:02 | <endojelly> | :t runWriter |
| 15:35:03 | <lambdabot> | forall w a. Writer w a -> (a, w) |
| 15:35:48 | <gnuvince_> | quicksilver: I'm trying to wrap my head around Monoids over functions, but I'm not sure I understand the intuition behind them |
| 15:35:57 | <gnuvince_> | > (1:) `mappend` (2:) $ [3] |
| 15:35:59 | <lambdabot> | [1,3,2,3] |
| 15:36:26 | <quicksilver> | that must be the instance I'm talking about |
| 15:36:39 | <quicksilver> | (f `mappend` g) x = f x `mappend` g x |
| 15:36:42 | <quicksilver> | pointwise mappend |
| 15:36:46 | <Cale> | qaz_: Well, in the interests of not keeping you too long, let's start here: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4992#a4993 |
| 15:36:47 | <Xen0x> | If you have defined a monad "QMonad a = ReaderT (Int) IO a" could you get the value out of the monad, just like using unsafePerforIO? |
| 15:36:49 | <quicksilver> | I'm pretty sure that's not in the standard libs though |
| 15:37:00 | <quicksilver> | must be a lambdabot extension |
| 15:37:06 | <Cale> | qaz_: Of course, the EQ case is going to be the most interesting. |
| 15:37:11 | <dschoepe> | gnuvince_: mappend for functions is composition |
| 15:37:23 | <doserj> | quicksilver: it is defined in Data.Monoid |
| 15:37:27 | <jmcarthur> | > (1:) . (2:) $ [3] |
| 15:37:29 | <lambdabot> | [1,2,3] |
| 15:37:35 | <jmcarthur> | ^^ is different from the above |
| 15:37:36 | <qaz_> | hmm yea i must be able to simplify that |
| 15:37:45 | <vixey> | Xen0x, It would not be anything like unsafePerformIO |
| 15:37:57 | <MyCatVerbs> | :t runReaderT |
| 15:37:59 | <lambdabot> | forall r (m :: * -> *) a. ReaderT r m a -> r -> m a |
| 15:38:10 | <MyCatVerbs> | Xen0x: you can get from the ReaderT Int (IO a) to (IO a) with runReaderT. |
| 15:38:19 | <Cale> | qaz_: Now, the trouble just becomes selection of a new root and an element to delete from either the left or right subtree. |
| 15:38:24 | <MyCatVerbs> | Xen0x: from there, you could use unsafePerformIO, but actually you probably don't want to. |
| 15:38:41 | <dons> | this needs help from a haskell person, http://stackoverflow.com/questions/876948/higher-kinded-generics-in-java |
| 15:38:46 | <MyCatVerbs> | Er, should not have put parens around the first (IO a) there. |
| 15:38:54 | <MyCatVerbs> | dons: oh DEAR me. |
| 15:39:00 | <Xen0x> | but with runReaderT, you don't lose the value carried around within the monad? |
| 15:39:25 | <dons> | quicksilver, Cale you guys should comment :) |
| 15:40:06 | <MyCatVerbs> | Xen0x: no? You have to *supply* that value in order to use runReaderT, so the value will still be in scope somewhere where you can use it. |
| 15:40:09 | <Cale> | qaz_: There are three cases, but they chain nicely. Either we find an element in the left subtree, delete it from there, and make that our new root, or we find an element in the right subtree, delete it from there, and make that our new root, or we fail to find an element in either, in which case we're left with a Leaf |
| 15:40:54 | <Cale> | qaz_: Maybe has useful functions for chaining things together in this way. |
| 15:41:07 | <TonyTheTiger> | how can i take a list and return the list but split into 2? |
| 15:41:43 | <jmcarthur> | :t \(x:xs) -> (x,xs) -- cheating |
| 15:41:44 | <lambdabot> | forall t. [t] -> (t, [t]) |
| 15:41:45 | <Xen0x> | MyCats; maybe I don't understand, but how can I use the runReaderT then, to get the IO a?. Just use runReaderT monad? |
| 15:41:58 | <jmcarthur> | :t \(x:xs) -> ([x],xs) -- slightly more correct cheating |
| 15:41:59 | <lambdabot> | forall t. [t] -> ([t], [t]) |
| 15:41:59 | <Xen0x> | where monad is of type; ;QMonad a |
| 15:42:03 | <MyCatVerbs> | Xen0x: runReaderT environment monad |
| 15:42:04 | <mmorrow> | splitAt, span, break |
| 15:42:19 | <TonyTheTiger> | how can i take a list and return the list but split into 2?? |
| 15:42:20 | <mmorrow> | @type splitAt 1 |
| 15:42:21 | <lambdabot> | forall a. [a] -> ([a], [a]) |
| 15:42:37 | <MyCatVerbs> | Xen0x: e.g. you have type QMonad a = ReaderT Int IO a. |
| 15:42:38 | <jmcarthur> | TonyTheTiger, mmorrow is helping you |
| 15:42:46 | <jmcarthur> | i was pretending to |
| 15:42:54 | <TonyTheTiger> | jmcarthur: yeah i just realised, gonna go test. |
| 15:42:55 | <TonyTheTiger> | sorry |
| 15:43:07 | <mmorrow> | TonyTheTiger: how do you want to determine _where_ to split it? |
| 15:43:17 | <MyCatVerbs> | Xen0x: when you make use of that, the types will work out like: (runReaderT (foo :: Int) (monad :: QMonad a)) :: IO a |
| 15:43:20 | <TonyTheTiger> | mmorrow: has to be in the middle |
| 15:43:33 | <MyCatVerbs> | (Unless I made a mistake, which happens ~_^) |
| 15:43:37 | <TonyTheTiger> | mmorrow: so it can only be on lists of equal length |
| 15:43:37 | <mmorrow> | ah, \xs -> splitAt (length xs `div` 2) xs |
| 15:43:41 | <mmorrow> | or something then |
| 15:44:00 | <TonyTheTiger> | what would happen if a list that wasnt even is input? |
| 15:44:07 | <TonyTheTiger> | if using an if case appropriate? |
| 15:44:09 | <mmorrow> | , 5 `div` 2 |
| 15:44:11 | <lunabot> | 2 |
| 15:44:31 | <MyCatVerbs> | TonyTheTiger: with mmorrow's solution there, if you give an odd-length input then the second list will be one element longer than the first list. |
| 15:45:08 | <mmorrow> | jmcarthur: did you ever attempt a gcc compile of a /dict/words switch trie? |
| 15:45:16 | <Xen0x> | MyCatVerbs; I get the picture now. I was only thinking about the passing around of the carried value, but when I use runReaderT I probably don't want that value to be in the Monad (QMonad) anymore, so I don;t need the carried values anymore |
| 15:45:21 | <qaz_> | Cale: the problem is the base case |
| 15:45:23 | <qaz_> | s |
| 15:45:26 | <TonyTheTiger> | MyCatVerbs: yeah im not allowed that, but methinks an if can fix it, but not sure if thats the "correct" way |
| 15:45:30 | <jmcarthur> | mmorrow, no i never got a chance this weekend |
| 15:45:36 | <jmcarthur> | mmorrow, i still plan to |
| 15:45:45 | <TonyTheTiger> | but thanks i didnt know of the split At functions |
| 15:46:23 | <mmorrow> | jmcarthur: cool, i'm gonna try to remember to leave it running next time i'm away from the computer too |
| 15:46:28 | <MyCatVerbs> | TonyTheTiger: well, where *do* you want the odd element to go if the list's length isn't even? |
| 15:46:54 | <Cale> | qaz_: I think it helps to have a function findDeleteMin :: BST a -> Maybe (a,BST a), and similar for max |
| 15:46:58 | <TonyTheTiger> | MyCatVerbs: its an exam question that im practicing, so that doesnt really matter |
| 15:47:47 | <MyCatVerbs> | TonyTheTiger: if it doesn't specify what to do with lists of odd lengths then your exam question doesn't contain enough information to determine the solution. :P |
| 15:48:22 | <Peaker> | in which case you can write all the solutions! |
| 15:48:24 | <TonyTheTiger> | MyCatVerbs: yeah i wouldnt be surprised. The questions I keep seeing everyone round here keeps saying how they are "bad" questions :( |
| 15:48:34 | <tetha> | I vote to read two lists from the user and return those if the input length is odd |
| 15:48:47 | <tetha> | I once did something like that and hilarious things happened later on |
| 15:49:06 | <roconnor> | @src ReaderT |
| 15:49:07 | <lambdabot> | Source not found. Where did you learn to type? |
| 15:49:10 | <jmcarthur> | TonyTheTiger, i would solve it for even lists and write your assumptions about what the question really wants |
| 15:49:22 | <roconnor> | @unmtl ReaderT r m a |
| 15:49:22 | <lambdabot> | r -> m a |
| 15:49:29 | <roconnor> | @unmtl Reader r (m a) |
| 15:49:29 | <lambdabot> | r -> m a |
| 15:49:47 | <jonathanturner> | trying to wrap my head around type inference. "let a x = \x -> x + x" works with a 10, but doesn't with a 10.4. |
| 15:49:48 | <jmcarthur> | well, and obviously have it do *something* with odd lengths, but i just mean make sure that there was ambiguity about what the question was asking |
| 15:50:04 | <mmorrow> | , |
| 15:50:05 | <jmcarthur> | > let a x = \x -> x + x in a 10 |
| 15:50:05 | <lunabot> | luna: <stdin>: Data.ByteString.hGetLine: end of file |
| 15:50:06 | <lambdabot> | Overlapping instances for Show (a -> a) |
| 15:50:06 | <lambdabot> | arising from a use of `s... |
| 15:50:07 | <roconnor> | @unmtl WriterT w m a |
| 15:50:07 | <lambdabot> | m (a, w) |
| 15:50:08 | <jmcarthur> | > let a x = \x -> x + x in a 10 10 |
| 15:50:10 | <lambdabot> | 20 |
| 15:50:13 | <jmcarthur> | > let a x = \x -> x + x in a 10 10.4 |
| 15:50:14 | <lambdabot> | 20.8 |
| 15:50:23 | <roconnor> | @unmtl m (Writer w a) |
| 15:50:23 | <lambdabot> | m (a, w) |
| 15:50:47 | <mmorrow> | @type \xs -> let n = length xs `div` 2 in if even n then [splitAt n xs] else [splitAt n xs, splitAt (n+1) xs] |
| 15:50:49 | <lambdabot> | forall a. [a] -> [([a], [a])] |
| 15:51:04 | <MyCatVerbs> | jonathanturner: if you type "let a = \x -> x + x" at GHCi's prompt, then it'll infer a monomorphic type for a. |
| 15:51:05 | <jmcarthur> | jonathanturner, you must be doing something different than i |
| 15:51:18 | <jmcarthur> | oh, yeah, ghci would do that |
| 15:51:52 | <MyCatVerbs> | jonathanturner: you've run into the monomorphism restriction. GHCi is defaulting to a :: (Integer -> Integer). |
| 15:52:18 | <MyCatVerbs> | If you define it by, let a x = x + x -- instead, then it will infer the correct type, (Num a) => a -> a. |
| 15:52:23 | <jonathanturner> | MyCatVerbs: I thought that might be the case, but "let b = \x -> x ++ x" works with both b [1] and b["bob"] |
| 15:53:02 | <MyCatVerbs> | jonathanturner: that's because b is being inferred as [a] -> [a], and there are no constraints at all on a. |
| 15:53:22 | <MyCatVerbs> | The monomorphism restriction only kicks in when there are typeclass constraints present. |
| 15:53:45 | <jonathanturner> | MyCatVerbs: that makes sense |
| 15:54:02 | <MyCatVerbs> | It's an artifact of a minor worry about efficiency that the Haskell98 committee had about polymorphic types and sharing. |
| 15:54:05 | <jonathanturner> | MyCatVerbs: still very much wrapping my head around this stuff |
| 15:54:18 | <jonathanturner> | MyCatVerbs: is it getting fixed in Haskell'? |
| 15:54:48 | <MyCatVerbs> | jonathanturner: yep. And it'll be turned off by default anyway in GHC 6.12 and up, AFAIK. |
| 15:54:55 | <Cale> | qaz: Oops! Those recursive cases are actually wrong in an obvious way ;) |
| 15:54:59 | <MyCatVerbs> | jonathanturner: long story short, it annoys the people who work on GHC itself too. :) |
| 15:55:03 | <jonathanturner> | MyCatVerbs: cool, not that it's bad or anything, just confusing |
| 15:55:35 | <Cale> | qaz: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4992#a4994 |
| 15:56:31 | <MyCatVerbs> | jonathanturner: it *is* bad enough that the people who hack on GHC for fun and profit hate it and want to make it go away. :) |
| 15:57:00 | <jonathanturner> | MyCatVerbs: you said they had monomorphic restrictions because of efficiency concerns? do you know if there is an implementation discussion about that? I'm learning Haskell, but also interested in the implementation side as wel |
| 15:57:47 | <MyCatVerbs> | The wiki page, http://www.haskell.org/haskellwiki/Monomorphism_restriction explains it better than I could. |
| 15:57:49 | <endojelly> | :t runWriter |
| 15:57:50 | <lambdabot> | forall w a. Writer w a -> (a, w) |
| 15:58:18 | <Cale> | jonathanturner: Basically, the concern is that when you have a value like (Num a) => a it is implemented internally by a (non-memoised) function from a Num dictionary to an appropriate value of the right type. |
| 15:58:28 | <Cale> | jonathanturner: That is, as a function Num a -> a |
| 15:58:55 | <Cale> | jonathanturner: So, things which look like constants can actually end up being functions, and being recomputed each time they are used. |
| 15:59:46 | <Saizan> | (the haskell report actually explains it best, imo) |
| 15:59:59 | <MyCatVerbs> | Except that it never actually comes up in practice any more. For starters, the optimiser's gotten cleverer. For seconds, it never came up that often anyway. |
| 16:00:05 | <Cale> | jonathanturner: The MR is just a terrible solution to this problem. It says that if you have a pattern binding (something which looks like a constant definition), it can't be typeclass polymorphic unless it has an explicit type signature. |
| 16:00:59 | <Cale> | So basically, what should have been a warning at best, is now an error. |
| 16:02:00 | <Cale> | I think it's safe to say, given the last 10 years or so of everyone having to deal with it, that it's a flaw in the standard. |
| 16:02:02 | <MyCatVerbs> | Haskell lets me make up type-level lists. oO |
| 16:02:26 | <Peaker> | I think the concept of compiler warnings is a bad/silly one. If you don't want to fix it -- you can't just leave it there as noise -- you'll miss the warnings you do want to fix. So it might as well be an "overridable error" that you can override with some pragma or such |
| 16:02:53 | <MyCatVerbs> | Peaker: oh hey, that gets subsumed by LANGUAGE pragmas. |
| 16:02:55 | <Cale> | MyCatVerbs: That comment earlier about Haskell's type system letting you get away with things you expected not to, what was that about? |
| 16:03:05 | <MyCatVerbs> | Cale: that. ^^ |
| 16:03:08 | <jonathanturner> | Peaker: that's not a bad idea, but it would slow new programmers down considerably |
| 16:03:15 | <Cale> | MyCatVerbs: Type level lists? |
| 16:03:16 | <Peaker> | MyCatVerbs: I'd rather these overrides were on a per-case basis, rather than a per-error-type basis |
| 16:03:33 | <Saizan> | you can already override MR by giving a type signature |
| 16:03:37 | <MyCatVerbs> | Peaker: to some extent, we already do this with things like -XOverlappingInstances. |
| 16:03:42 | <Cale> | Peaker: But it should never prevent a program from compiling. |
| 16:03:56 | <Saizan> | but still, it's awful to have to explain such a quirk to beginners |
| 16:04:01 | <hatds> | I think Peaker is talking about the notion of compiler warnings in general |
| 16:04:10 | <Cale> | We shouldn't prevent programs from compiling over minor potential performance problems. |
| 16:04:11 | <MyCatVerbs> | Overlapping instances are an error in H98, but asking for -XOverlappingInstances turns the check off. |
| 16:04:20 | <Peaker> | Cale: I think it should -- because mtime-based checking means that you're going to accidentally ignore all warnings if it did compile |
| 16:04:33 | <Cale> | mtime? |
| 16:04:42 | <Peaker> | Cale: its not preventing compilation, its just delaying it/requiring that you add an override |
| 16:04:47 | <roconnor> | Saizan: I believe that there are some obtuse cases were you cannot simply add a type signature. |
| 16:04:52 | <MyCatVerbs> | So there's no reason you couldn't stick lots of extra warnings in as LANGUAGE features. :) |
| 16:05:08 | <Cale> | Peaker: Well, in that case, we should remove it altogether. |
| 16:05:10 | <Peaker> | Cale: modification times on files is the common system that is unfortunately used to determine whether to recompile -- and any warnings that were issued before are not re-issued |
| 16:05:11 | <roconnor> | Saizan: thing of the MR applied in a where clause to something that contains type variables from the main function. |
| 16:05:14 | <roconnor> | think |
| 16:05:21 | <Cale> | Peaker: huh? |
| 16:05:24 | <Cale> | Peaker: Since when? |
| 16:05:42 | <Cale> | Peaker: I expect my compiler to report the exact same thing when given the same inputs. |
| 16:05:45 | <MyCatVerbs> | Cale: if I have F.hs and G.hs, compile both, F emits warnings. |
| 16:06:00 | <Cale> | Does GHC actually do that? |
| 16:06:05 | <MyCatVerbs> | Cale: and then modify G and recompile, where G depends on F... I won't get the warnings from F repeated to me. |
| 16:06:13 | <endojelly> | :t everywhere' |
| 16:06:14 | <lambdabot> | forall a. (Data a) => (forall a1. (Data a1) => a1 -> a1) -> a -> a |
| 16:06:16 | <endojelly> | :t everywhereM' |
| 16:06:17 | <lambdabot> | Not in scope: `everywhereM'' |
| 16:06:18 | <endojelly> | :t everywhereM |
| 16:06:19 | <lambdabot> | forall (m :: * -> *) a. (Monad m, Data a) => GenericM m -> a -> m a |
| 16:06:24 | <Cale> | MyCatVerbs: Oh, because F is already compiled, sure. |
| 16:06:30 | <hatds> | MyCatVerbs: well, that's what separate compilation should do, no? |
| 16:06:51 | <MyCatVerbs> | hatds: well, I assume it ought to, but then I've never actually tried the alternative. |
| 16:06:54 | <Cale> | If there's an F.o and F.hs doesn't need to be compiled, then of course you won't see the warnings again. |
| 16:07:02 | <Peaker> | Cale: the prevalent build systems in use do not re-report warnings, which is another reason to not create the final output if there are warnings |
| 16:07:13 | <Cale> | Peaker: You mean cabal? |
| 16:07:15 | <Peaker> | Cale: its too easy to miss warnings by accident |
| 16:07:18 | <Cale> | Peaker: or GHC? |
| 16:07:20 | <Peaker> | Cale: cabal, ghc, make |
| 16:07:25 | <Cale> | Interesting. |
| 16:07:39 | <endojelly> | :t gmapT |
| 16:07:39 | <MyCatVerbs> | Peaker: no it isn't? Cabal's normal compilation output is *really* terse, one line per file. |
| 16:07:40 | <lambdabot> | forall a. (Data a) => (forall b. (Data b) => b -> b) -> a -> a |
| 16:07:41 | <endojelly> | :t gmapM |
| 16:07:42 | <lambdabot> | forall (m :: * -> *) a. (Monad m, Data a) => (forall a1. (Data a1) => a1 -> m a1) -> a -> m a |
| 16:07:49 | <MyCatVerbs> | Peaker: source warnings show up like glowy beacons in the middle of it. |
| 16:07:50 | <Cale> | I'm going to have to try this. |
| 16:07:52 | <quicksilver> | I don't find it easy to miss warnings by accident. |
| 16:08:00 | <Peaker> | MyCatVerbs: but then when you recompile, you don't get the warnings again |
| 16:08:03 | <Saizan> | roconnor: with the constraint on some other variable, yeah, but it's not so common i'd think |
| 16:08:06 | <Cale> | Somehow I can't believe that it would be the case. |
| 16:08:37 | <Peaker> | quicksilver: I just saw some mention of accidentally ignored warnings on Haskell blogs -- and it has bitten me before too |
| 16:08:45 | <Peaker> | quicksilver: its another thing I have to keep in mind when compiling |
| 16:08:51 | <MyCatVerbs> | Peaker: The only time you do seperate recompilation is when you're modifying the package yourself. Otherwise you're building the whole thing from scratch from Hackage, most likely. |
| 16:09:04 | <Peaker> | MyCatVerbs: right, and warnings are less interesting in that scenario |
| 16:09:08 | <MyCatVerbs> | Peaker: and if you're working on it yourself, then you just turn -Werror on if you care about warnings. |
| 16:09:16 | <roconnor> | Saizan: and it also cuts both ways. You cannot monomorphically restrict with the MR off by adding a signature. ... I guess the real problem is not being able to give signatures to any subexpression. |
| 16:09:21 | <Cale> | Peaker: It's a lie. GHC reports warnings every time a module is compiled. |
| 16:09:22 | <Peaker> | MyCatVerbs: Right, I suggest -Werror as a default |
| 16:09:25 | <MyCatVerbs> | (And runhaskell Setup clean, too.) |
| 16:09:31 | <Peaker> | Cale: but it doesn't recompile if a final output was produced |
| 16:09:46 | <Saizan> | roconnor: there's always `asTypeOf` |
| 16:09:56 | <Peaker> | Cale: if you were fixing some errors you got from a compilation, and then re-issue a recompile expecting to fix the remaining errors, you're going to ignore the warnings that you didn't fix |
| 16:10:02 | <Peaker> | Cale: (in files that had only warnings) |
| 16:10:14 | <MyCatVerbs> | Peaker: that won't help much. It'll break a whole pile of existing code for exceedingly little benefit. It's not like you can't put Werror in the .cabal file yourself, so having it not be the default doesn't prevent you from doing anything. |
| 16:10:25 | <Cale> | You'll get all the warnings for the module you just modified. |
| 16:10:42 | <Peaker> | MyCatVerbs: It might not be the best thing to do now, but I think it would be far better if it was that way in the first place |
| 16:10:56 | <Cale> | There's an easy solution though. rm *.o |
| 16:10:59 | <Peaker> | Cale: right, and you'll accidentally ignore all the warnings in modules that "successfully" compiled |
| 16:11:05 | <Peaker> | Cale: indeed, and -Werror too |
| 16:11:11 | <MyCatVerbs> | Peaker: and I do hope we can skip the "but undisciplined programmers will just ignore warnings", because IMHO undisciplined programmers will write crap code anyway no matter how fussy you make the compiler. |
| 16:11:16 | <Peaker> | Cale: IMO it should be a default |
| 16:11:23 | <Cale> | Peaker: But the warnings are not that important anyway |
| 16:11:31 | <roconnor> | Saizan: that requires writing an expression with the same type as thing thing you are trying to type, which can be diffcult, and I'm not convinced it is always possible. But it is probably always possible. |
| 16:11:41 | <Cale> | Actually, I never use -Wall |
| 16:11:56 | <Peaker> | Cale: Non-exhaustive pattern matches are a horrible thing to catch at runtime, IMO |
| 16:12:15 | <Cale> | Well, sure, but they're something I essentially just never write. |
| 16:12:16 | <hatds> | sometimes your function is supposed to be partial :) |
| 16:12:22 | <Peaker> | Cale: Fixing warnings costs nearly nothing, not fixing them has a non-negligent chance of being an actual bug |
| 16:12:52 | <Peaker> | Cale: If you're careful enough, of course you don't need the warnings. -Wall frees you from having to be careful about several things |
| 16:13:11 | <quicksilver> | -Wall gives warnings about various kinds of perfectly valid code |
| 16:13:13 | <Saizan> | roconnor: it's generally easy if you define an appropriately typed function using undefined as body |
| 16:13:15 | <quicksilver> | I do not find it useful. |
| 16:13:17 | <Cale> | I suppose. But quite often I actually don't want to write type signatures on things. |
| 16:13:36 | <Peaker> | quicksilver: type signatures on top-level names are nice, IMO, what else does it have that shows up often? |
| 16:13:37 | <roconnor> | Saizan: ya |
| 16:13:45 | <quicksilver> | -Wall frees you from having valuable free time, but forcing you to spend time fixing things that don't need fixing. |
| 16:13:46 | <Cale> | (In the case that they are noisy and unhelpful) |
| 16:13:59 | <MyCatVerbs> | Cale: I don't know about you, but without at least type declarations, I sometimes forget what entire chunks of code were for. ;) |
| 16:14:10 | <quicksilver> | Peaker: type-level signatures on top-level names, incomplete patterns, I don't remember what else. |
| 16:14:14 | <Peaker> | quicksilver: I think that it is a negligible proportion of the time you spend coding it.. |
| 16:14:21 | <quicksilver> | Peaker: I tried it once, thought "This is stupid" and have never used it since. |
| 16:14:23 | <Peaker> | quicksilver: incomplete patterns are never bugs? |
| 16:14:25 | <Cale> | MyCatVerbs: For some types of code they are very useful, for other types of code they are not. |
| 16:14:29 | <Peaker> | quicksilver: (in your code/ |
| 16:14:30 | <quicksilver> | Peaker: all kinds of things are bugs. |
| 16:14:38 | <quicksilver> | Peaker: when I write an incomplete pattern, I know what I have done. |
| 16:14:39 | <Saizan> | warning about name shadowing gets annoying most of the time, it should only warn about a really small surrounding scope |
| 16:14:48 | <quicksilver> | it is no more likely to be a bug than any other thing I write. |
| 16:15:38 | <Peaker> | quicksilver: I find it hard to believe that inexhaustive-pattern-matches are no more likely to be bugs than other things |
| 16:15:39 | <Cale> | That's the nice thing about algebraic types, it's really hard to write incomplete pattern matches in the first place. |
| 16:15:44 | <quicksilver> | yeah, the shadowing warning is another unhelpful one. |
| 16:16:03 | <Peaker> | quicksilver: When it is unambiguous (type-wise), sure. When its ambiguous? It's saved me before |
| 16:16:19 | <hatds> | stuff about patterns (overlapping, non-exhaustive) would be more useful to be told about while you are in the text editor |
| 16:16:38 | <Cale> | hatds: I agree. |
| 16:16:40 | <Peaker> | hatds: in a non-textual code editor it would be much easier :) |
| 16:16:54 | <TonyTheTiger> | how can I do the same thing as zip but on a list using list comprehension? |
| 16:16:58 | <Peaker> | Indeed a non-textual code editor would make most of these points completely moot, and you'd get type-inference "on-the-fly" |
| 16:17:04 | <Cale> | The compiler should certainly be able to tell me, on command, when pattern matches are incomplete. |
| 16:17:05 | <quicksilver> | Peaker: almost every haskell program I have ever written has at least one correct inexhaustive pattern |
| 16:17:12 | <Berengal> | TonyTheTiger: Explain |
| 16:17:17 | <Saizan> | it's easy in a textual editor too, see eclipse and the other ides :) |
| 16:17:22 | <quicksilver> | Peaker: adding a warning to all that code would be a misfeature. |
| 16:17:23 | <Cale> | quicksilver: Which wasn't a call to a library function? |
| 16:17:29 | <MyCatVerbs> | Cale: the other nice thing about algebraic types is that it's always possible to detect incomplete pattern matches when you do make 'em. ;) |
| 16:17:33 | <quicksilver> | Cale: some are, some aren't. |
| 16:17:37 | <Peaker> | quicksilver: I dislike that in programs, I try to refactor it into not having the impossible constructors in the first place.. do you have examples? |
| 16:17:39 | <roconnor> | TonyTheTiger: there is an extension called parallel list comprehensions |
| 16:17:46 | <TonyTheTiger> | Berengal: e.g [1,2,3] [4,5,6] becomes [1,4,2,5,3,6] |
| 16:17:53 | <Peaker> | quicksilver: is it really that painful to explicitly handle the _ -> ... case? |
| 16:17:55 | <Cale> | MyCatVerbs: Of course, once you add guards into the mix, things are more complicated |
| 16:17:56 | <quicksilver> | Peaker: suppose you make a pass over an AST which removes variables. |
| 16:17:58 | <roconnor> | > [(x,y) | x <- [1..] | y <- [2,4..10]] |
| 16:17:59 | <lambdabot> | [(1,2),(2,4),(3,6),(4,8),(5,10)] |
| 16:18:15 | <quicksilver> | Peaker: after that you have an AST which never uses the 'Var' constructor. |
| 16:18:21 | <MyCatVerbs> | Cale: you would bring Turing-complete predicates into it, wouldn't you? Feh. |
| 16:18:26 | <quicksilver> | when you operate on that, you don't want ot handly the useless case. |
| 16:18:49 | <quicksilver> | but it's a huge amount of boilerplate to define a fresh data type for that |
| 16:18:54 | <Peaker> | quicksilver: Why not put it under an anything-else -> error "Broken assumptions"? |
| 16:18:58 | <quicksilver> | especially if there are multiple such intermediate steps. |
| 16:19:06 | <quicksilver> | Peaker: because the compiler does that for me, for free! |
| 16:19:09 | <Saizan> | but then you don't get to write amusing errors like "the impossible happened!" |
| 16:19:19 | <quicksilver> | with a _ -> error "inexhaustive patterns" |
| 16:19:20 | <Berengal> | > concatMap (\(a,b) -> [a,b]) . zip $ [1,2,3] [4,5,6] |
| 16:19:20 | <hatds> | lol |
| 16:19:21 | <lambdabot> | Couldn't match expected type `[(t, t)]' |
| 16:19:22 | <Peaker> | quicksilver: its not free -- it costs you missing out on the cases where you did forget |
| 16:19:29 | <quicksilver> | which, IIRC, is actually *better* than an error message I can write |
| 16:19:37 | <quicksilver> | since it contains a function name and even line number? |
| 16:19:40 | <Berengal> | > concatMap (\(a,b) -> [a,b]) . zip [1,2,3] $ [4,5,6] |
| 16:19:41 | <lambdabot> | [1,4,2,5,3,6] |
| 16:19:42 | <Saizan> | yup |
| 16:19:51 | <Saizan> | even the column! |
| 16:19:55 | <quicksilver> | ACTION nods |
| 16:20:00 | <Peaker> | hmm.. there should be an "error" that does that too |
| 16:20:09 | <hatds> | yea, that's what I've been saying |
| 16:20:20 | <quicksilver> | that would certainly help. |
| 16:20:27 | <Berengal> | How come I always get the first expression given to lambdabot wrong when I'm in a public channel? |
| 16:20:32 | <quicksilver> | But I have a labouring suspicion you're solving a non-problem :) |
| 16:20:56 | <quicksilver> | because I honestly can't think of a single case where the non-exhaustive pattern match warning has helped me :) |
| 16:20:59 | <Peaker> | quicksilver: Its not a problem for me most of the time, because I use -Werror -Wall anyhow.. But I do forget to enable them both on new files I compile sometimes |
| 16:21:01 | <hatds> | there is an "assert" function for ghc which will spew out the line number |
| 16:21:02 | <quicksilver> | not even in ML, where it's on by default IIRC. |
| 16:21:09 | <TonyTheTiger> | Berengal: What you wrote is that usin a list comprehension? |
| 16:21:52 | <Peaker> | quicksilver: well, I heard once that "recursion is the assembly of FP" -- and in a sense I think pattern-matching is too. I don't find myself using it all that often. When I did use it more, it did catch bugs |
| 16:21:55 | <Berengal> | TonyTheTiger: No, I don't think it's possible in just a list comprehension... |
| 16:22:28 | <TonyTheTiger> | Berengal: Are you sure? my practice exam asks me to do it using a list comprehension |
| 16:22:48 | <Cale> | Berengal: I don't understand that question... |
| 16:22:59 | <Cale> | Berengal: Oh, I missed the word "wrong" |
| 16:23:44 | <Jedai> | TonyTheTiger: That would be really weird and stupid |
| 16:24:00 | <Berengal> | TonyTheTiger: A list comprehension always constructs single elements of a list. You want to create two and two elements, which means you need to do something else |
| 16:24:10 | <Cale> | huh? |
| 16:24:32 | <Jedai> | TonyTheTiger: I think the best way is probably to use explicit recursion in this case, it's probably the clearest you can do : |
| 16:24:34 | <Cale> | If you're doing a concatMap anyway, you might as well write a list comprehension |
| 16:24:37 | <quicksilver> | Peaker: sure. You use pattern matching for the basic operations which apply to a type, normaly. |
| 16:24:51 | <endojelly> | :t mapAndUnzip |
| 16:24:52 | <lambdabot> | Not in scope: `mapAndUnzip' |
| 16:24:57 | <endojelly> | :t unzipWith |
| 16:24:58 | <lambdabot> | Not in scope: `unzipWith' |
| 16:25:00 | <Berengal> | > [[a,b] | a <- [1,2,3] | b <- [4,5,6]] |
| 16:25:01 | <lambdabot> | [[1,4],[2,5],[3,6]] |
| 16:25:06 | <Saizan> | > [x | (a,b) <- zip [1..3] [4..6], x <- [a,b]] |
| 16:25:07 | <lambdabot> | [1,4,2,5,3,6] |
| 16:25:09 | <Jedai> | interleave (x:xs) (y:ys) = x : y : interleave xs ys |
| 16:25:09 | <Jedai> | interleave _ _ = [] |
| 16:25:15 | <Saizan> | not that hard :) |
| 16:25:21 | <vixey> | Saizan very nice |
| 16:25:29 | <quicksilver> | Peaker: then you write more sophisticated claculations in terms of those simple ones. |
| 16:25:40 | <hatds> | matching on a tuple or a product type and binding each component to a variable is not really pattern matching |
| 16:25:42 | <Cale> | Saizan wrote the code I was about to write too :) |
| 16:25:43 | <Jedai> | Saizan: Pretty nice :) |
| 16:25:49 | <Berengal> | Saizan: I keep forgetting that list comprehensions are sugar for the list monad... very nice |
| 16:25:55 | <roconnor> | > tan (10^100) :: CReal |
| 16:25:56 | <lambdabot> | 0.4012319619908143541857543436532949583239 |
| 16:25:58 | <vixey> | ACTION didn't figure out what Saizan wrote |
| 16:26:01 | <hatds> | well it is, but it is rare that matching will fail |
| 16:26:02 | <quicksilver> | Peaker: that means you don't pattern match very often, which makes it even more likely you don't make non-exhaustive pattern errors :) |
| 16:26:10 | <roconnor> | > tan (10^100) |
| 16:26:11 | <lambdabot> | -3.302509482989562e-2 |
| 16:26:54 | <ziman> | > (sin (10^100) :: Double, sin (10^100) :: CReal) |
| 16:26:56 | <lambdabot> | (3.30071000245921e-2,-0.3723761236612766882620866955531642957197) |
| 16:28:09 | <Cale> | http://www.smbc-comics.com/ -- ahaha |
| 16:28:48 | <TonyTheTiger> | Berengal: turns out this was the answer, I understand it (somewhat) but didnt know haskell could use comprehensions like this |
| 16:28:50 | <TonyTheTiger> | concat [[x,y]|(x,y) <- zip xs ys] |
| 16:29:22 | <Cale> | TonyTheTiger: Well, you can even move the concat inside the comprehension as Saizan showed, by adding another generator |
| 16:29:24 | <Berengal> | TonyTheTiger: That was basically what my concatMap did above. Also, Saizan did it using just a comprehension |
| 16:29:27 | <Jedai> | TonyTheTiger: There is a concat, so it's not exactly a "pure" list comprehension |
| 16:29:38 | <Cale> | [z | (x,y) <- zip xs ys, z <- [x,y]] |
| 16:30:13 | <TonyTheTiger> | ohh sorry must have missed the answers posted above |
| 16:30:21 | <Berengal> | > do (a,b) <- zip [1,2,3] [4,5,6]; x <- [a,b]; return x |
| 16:30:22 | <lambdabot> | [1,4,2,5,3,6] |
| 16:30:30 | <TonyTheTiger> | [z | (x,y) <- zip xs ys, z <- [x,y]] <- this is a "pure" list comprehension then? |
| 16:30:31 | <Jedai> | TonyTheTiger: there is a zip too... I would argue that the question is pretty bad, it should not say that you have to use list comprehension |
| 16:31:33 | <Jedai> | TonyTheTiger: more or less pure, there is a zip inside, but it could be argued that the outermost expression is a list comprehension |
| 16:31:38 | <Cale> | I think it's a good exercise in making use of list comprehensions |
| 16:32:01 | <ziman> | how efficient is concat [[x,y] |
| 16:32:03 | <Berengal> | List comprehensions are good for understanding monads, but not much else |
| 16:32:05 | <ziman> | how efficient is concat [[x,y] | ... ? |
| 16:32:09 | <Berengal> | In my opinion, of course |
| 16:32:14 | <Cale> | ziman: Just as efficient as the other way |
| 16:32:21 | <lilac> | > (\xs ys -> [if n `mod` 2 == 0 then xs !! fromIntegral (n `div` 2) else ys !! fromIntegral (n `div` 2) | n <- [0..min (genericLength xs) (genericLength ys :: Natural) * 2 - 1]]) [1,2,3] [4,5,6] |
| 16:32:22 | <lambdabot> | [1,4,2,5,3,6] |
| 16:32:24 | <lilac> | there we go |
| 16:32:36 | <Jedai> | Cale: Right, but in this case the answer should be entirely formulated in term of list comprehension |
| 16:32:55 | <ziman> | Cale, "the other way" being your [z | ...] or the explicit recursive version? |
| 16:33:10 | <Jedai> | lilac: Wow !! ^^ |
| 16:33:30 | <qaz> | how would you handle timeouts in Haskell? like the Erlang runtime has built-in support for handling stuff that takes to long |
| 16:33:32 | <lilac> | > (\xs ys -> [[xs !! fromIntegral (n `div` 2), ys !! fromIntegral (n `div` 2)] !! fromIntegral (n `mod` 2) | n <- [0..min (genericLength xs) (genericLength ys :: Natural) * 2 - 1]]) [1,2,3] [4,5,6] |
| 16:33:33 | <lambdabot> | [1,4,2,5,3,6] |
| 16:33:36 | <lilac> | better :) |
| 16:33:41 | <ziman> | > zipWith id (cycle [const, const id]) [1, 2, 3] [4, 5, 6] |
| 16:33:42 | <lambdabot> | Couldn't match expected type `[t1] -> t' |
| 16:33:48 | <Jedai> | Cale: I think it's probably less efficient than the explicit recursive version, no ? And less clear too |
| 16:34:43 | <ziman> | > (\xs ys -> zipWith id (cycle [uncurry const, uncurry $ const id]) (zip xs ys)) [1,2,3] [4,5,6] |
| 16:34:45 | <lambdabot> | [1,5,3] |
| 16:34:46 | <Berengal> | > zip [1,2,3] [4,5,6] >>= (\(a,b) -> [a,b]) |
| 16:34:48 | <lambdabot> | [1,4,2,5,3,6] |
| 16:34:53 | <ziman> | ah. :) |
| 16:35:18 | <Jedai> | > let (x:xs) /\/ (y:ys) = x : y : (xs /\/ ys); _ /\/ _ = [] in [1..4] /\/ [5..8] |
| 16:35:19 | <lambdabot> | [1,5,2,6,3,7,4,8] |
| 16:35:26 | <lilac> | > [0 .. genericLength [0..] :: Natural] |
| 16:35:31 | <lambdabot> | * Exception: stack overflow |
| 16:35:33 | <lilac> | :( |
| 16:35:41 | <lilac> | broken enumFrom for Natural? |
| 16:36:09 | <roconnor> | @src genericLength |
| 16:36:12 | <lambdabot> | genericLength [] = 0 |
| 16:36:14 | <lambdabot> | genericLength (_:l) = 1 + genericLength l |
| 16:36:32 | <lilac> | > enumFromTo 0 (fix (1+)) :: [Natural] |
| 16:36:34 | <lambdabot> | * Exception: stack overflow |
| 16:36:44 | <qaz> | hmm the whole Maybe and Monad stuff works a lot neater with a language that has pattenrmatching right? |
| 16:36:47 | <lilac> | > min (fix (1+)) 42 :: Natural |
| 16:36:48 | <lambdabot> | 42 |
| 16:36:48 | <roconnor> | lilac: seems like it |
| 16:36:57 | <qaz> | my erlang-Maybe was a lot nicer than my Clojure one |
| 16:37:15 | <lilac> | hmm. that's unfortunate. so my solution is incorrect by extension then ;-( |
| 16:37:43 | <Jedai> | qaz: pzttern matching is nice for a lot of things, though you don't need it to make Maybe nice to use, maybe is enough |
| 16:37:49 | <Jedai> | @type maybe |
| 16:37:52 | <lambdabot> | forall b a. b -> (a -> b) -> Maybe a -> b |
| 16:38:12 | <lilac> | Jedai: "pzttern": pattern match failure |
| 16:38:20 | <Twey> | Hahaha |
| 16:39:13 | <vixey> | > enumFromTo 0 infinity |
| 16:39:14 | <lambdabot> | * Exception: stack overflow |
| 16:39:22 | <vixey> | > enumFrom |
| 16:39:23 | <lambdabot> | Overlapping instances for Show (a -> [a]) |
| 16:39:23 | <lambdabot> | arising from a use of ... |
| 16:39:26 | <vixey> | > enumFrom :: [Natural] |
| 16:39:27 | <lambdabot> | Couldn't match expected type `[Natural]' |
| 16:39:32 | <Jedai> | > head (enumFrom 0) |
| 16:39:34 | <lambdabot> | 0 |
| 16:39:42 | <roconnor> | lilac: enumFromTo x y = map toEnum [fromEnum x .. fromEnum y] |
| 16:39:42 | <Jedai> | > head (enumFrom 0 :: [Natural]) |
| 16:39:43 | <lambdabot> | 0 |
| 16:39:50 | <roconnor> | lilac: those defaults really need to be overridden |
| 16:40:16 | <Jedai> | > genericLength (enumFrom 0) :: Natural > 5 |
| 16:40:17 | <lambdabot> | Only unit numeric type pattern is valid |
| 16:40:20 | <roconnor> | -- NOTE: these default methods only make sense for types |
| 16:40:22 | <roconnor> | -- that map injectively into Int using fromEnum |
| 16:40:25 | <Jedai> | > (genericLength (enumFrom 0) :: Natural) > 5 |
| 16:40:26 | <lambdabot> | True |
| 16:40:30 | <roconnor> | which is not the case for Nat |
| 16:41:09 | <vixey> | qaz: Can't you add pattern matching to clojure? |
| 16:43:07 | <vixey> | > (genericLength (enumFrom 0) :: Natural) |
| 16:43:11 | <lambdabot> | * Exception: stack overflow |
| 16:43:43 | <Jedai> | vixey: This one makes sense |
| 16:43:45 | <vixey> | > let _ + _ = error "stack overflow" in 1 + 1 |
| 16:43:46 | <lambdabot> | * Exception: stack overflow |
| 16:44:42 | <Eelis> | the lhs2tex manual doesn't mention coloured syntax highlighting. is this not supported? |
| 16:44:46 | <qaz> | lol dont realize how good monads are until you try a functional language without them :P |
| 16:44:57 | <roconnor> | lilac: source: http://hackage.haskell.org/packages/archive/numbers/2008.4.20.1/doc/html/src/Data-Number-Natural.html |
| 16:45:14 | <roconnor> | lilac: it should be easy to patch. |
| 16:45:42 | <roconnor> | lilac: then you can upload a new version to hackage and Cale can recompile lambdabot. |
| 16:45:50 | <roconnor> | lilac: oh an then tell augustss_ too |
| 16:47:43 | <Eelis> | can hscolour be used with lhs2tex, perhaps? |
| 16:47:55 | <kyevan> | BEEP |
| 16:50:06 | <malcolmw> | Eelis: my guess would be that hscolour and lhs2tex are either/or. But you could try it and see what happens (both ways round) |
| 16:50:44 | <Eelis> | malcolmw: well, i run lhs2tex on literate haskell, so i'm not sure how i could squeeze hscolour in there. but i'll have a look |
| 16:50:52 | <vixey> | http://www.loper-os.org/?p=41 |
| 16:51:04 | <vixey> | it says 'can we instead build on the idea that a computer program is a mathematical object that can be understood through logic' |
| 16:51:14 | <kyevan> | ACTION glares at ghc |
| 16:51:24 | <kyevan> | manpages, damnit! |
| 16:52:30 | <Apocalisp> | > length $ tails [1..26] >>= inits |
| 16:52:31 | <lambdabot> | 378 |
| 16:56:13 | <malcolmw> | Eelis: looking at the lhs2tex manual, I see that you can substitute different formatting for almost any element, e.g. keyword, conid, pragma |
| 16:56:24 | <bremner> | kyevan: man pages exist, at least on Debian. |
| 16:56:43 | <malcolmw> | Eelis: see Table 3 on page 36, wrt the %subst directive |
| 16:56:47 | <kyevan> | Not here, though... >_> |
| 16:57:20 | <bremner> | complain to your linux distro, unless your linux distro is VMS or Windows or something... |
| 16:57:38 | <kyevan> | Somehow I doubt Apple cares :P |
| 16:57:44 | <bremner> | or you didn't install the distro ghc, which I guess is pretty likely |
| 16:57:54 | <bremner> | ah, VMS with bling :-) |
| 16:58:06 | <kyevan> | Well. I suppose macports is the pokereyd person, not Apple. |
| 16:58:23 | <roconnor> | vixey: I always thought the future of computing was biology, not logic; I will now read lamport's article. |
| 16:58:24 | <adamvo> | ACTION wonders where the Functor ((,) t) instance has gone |
| 16:59:01 | <vixey> | roconnor: well some sya that logic is completely based on biology |
| 16:59:02 | <MyCatVerbs> | adamvo: Control.Monad.Instances. |
| 16:59:12 | <Eelis> | malcolmw: yes, but i'm reluctant to take that route. i also think there's more to syntax highlighting than just replacing keywords. i would also want highlighting for things like literals, punctuation, and different kinds of identifiers (ones that start with a capital, and ones that don't, for example) |
| 16:59:14 | <kyevan> | Also, Debian creates their own manpages if upstream lacks them... :J |
| 16:59:37 | <adamvo> | MyCatVerbs: thanks |
| 16:59:44 | <bremner> | kyevan: sure, but they are always freely usable |
| 16:59:58 | <malcolmw> | Eelis: well, that is exactly the categorisation that lhs2tex (and hscolour) give you |
| 17:00:34 | <Eelis> | malcolmw: oh, i see. interesting |
| 17:00:51 | <kyevan> | Yeah, Debian's manpages are Debian-made :J |
| 17:00:55 | <roconnor> | vixey: but I mean, I expect computer programs will be "grown" using genetic algorithms and in an "environment" of test harnesses that will mould the program into the desired functionality. |
| 17:01:10 | <MyCatVerbs> | roconnor: oi, genetic *programming*. :) |
| 17:01:22 | <qaz> | how would you handle timeouts in Haskell? like the Erlang runtime has built-in support for handling stuff that takes to long |
| 17:01:25 | <malcolmw> | Eelis: oh, actually, now I look closely at the lhs2tex table, it does look more specific - categorisation plus more info, like the first character of a conid (upper-case identifier) |
| 17:01:35 | <vixey> | roconnor, hat sounds cool :) I think it's one of many paradaigms |
| 17:01:37 | <kyevan> | So, my glaring still stands, since the main GHC distribution lacks them, so... |
| 17:01:38 | <MyCatVerbs> | roconnor: GAs are a slightly wider field, including some strictly less powerful things too. :) |
| 17:01:53 | <Eelis> | malcolmw: i'll certainly play around with those, then. thanks! |
| 17:02:01 | <jmcarthur> | qaz, depends what you are timing. pure computation? IO? |
| 17:02:11 | <jmcarthur> | any way you look at it, you need IO to get the times |
| 17:02:18 | <roconnor> | MyCatVerbs: fair |
| 17:02:45 | <jmcarthur> | but if it's pure, it helps to have some abstraction that allows you to pause and resume the computation so you can go to IO to check the time and stuff |
| 17:02:56 | <malcolmw> | Eelis: anyway, the default definitions are in lhs2TeX.fmt, so you could just try adding some colours in there |
| 17:02:58 | <jmcarthur> | or perhaps use threads to do something similar |
| 17:03:24 | <MyCatVerbs> | qaz: there's a Hackage package for things like this (attempting possibly-nonterminating pure computations with timeouts and other such safeties, all in IO of course), but I can't remember what it's called. |
| 17:04:05 | <MyCatVerbs> | qaz: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/ChasingBottoms |
| 17:06:48 | <MyCatVerbs> | qaz: I suppose it's overkill for the purposes of just trying to evaluate things with timeouts, but still. It might come in handy to have the extra firepower if you want to go debugging really huge expressions =) |
| 17:09:00 | <cedricshock> | I was looking at a simple http server, and it inspired a question about IO. Let's say I have an interactive process that does something like looking up a reverse DNS request to write to the log. I want to serve the page as fast as possible, but don't want to do the DNS request again to put in the data given to the page handler, which is pure. |
| 17:10:26 | <cedricshock> | How could I accomplish this? forkIO the DNS request (and the log writing) with an STM variable that gets passed into the page handler? Is it impossible for the page handler to be pure and lazy in IO (my guess)? |
| 17:12:50 | <mmorrow> | qaz: System.Timeout |
| 17:13:22 | <kyevan> | Hmm. Has anyone used TextWrangler on the mac with Haskell? |
| 17:13:36 | <MyCatVerbs> | cedricshock: the easy way is to just forkIO the whole (lookupDNS >>= logToDisk) action. |
| 17:13:42 | <kyevan> | I'm trying to get it to let me easily load the current file in ghci >_> |
| 17:14:06 | <cedricshock> | When you bind a in f :: a -> b, does the sequence generating a necessarily get executed. I don't think so, so then the pure f a->b can have some wonderful uglies in its a (which may not be an a yet). Then it would need to be guaranteed that the DNS lookup would succeed eventually or never terminate, which would just mean the type for it would need to be some kind of Maybe. |
| 17:14:40 | <MyCatVerbs> | cedricshock: personally, I'd write one thread permanently listened on a Chan String (or Chan ByteString) and wrote whatever got written to that channel to disk, and then logToDisk s = putChan toDiskLogger s; |
| 17:15:16 | <cedricshock> | MyCatVerbs: Yeah, but can I lazily get the dns lookup out of lookupDNS into the page request info for the handler without waiting on it succeeding so it only waits on handlers that need it? |
| 17:15:19 | <MyCatVerbs> | cedricshock: just do DNS lookup in the IO monad and multithread it. This is not a good place to use lazy IO. |
| 17:16:26 | <cedricshock> | No. I want the DNS lookup to be eager, but share the lookup with the page handler that will only wait for it to be done when it needs it. |
| 17:16:34 | <MyCatVerbs> | cedricshock: you could do let dnsresult = (unsafePerformIO lookupDNS), which would then defer the DNS lookup until it's needed, but I suspect you wouldn't gain anything interesting by doing that. |
| 17:17:32 | <MyCatVerbs> | Ah, right. Hrmn. I suspect that the best answer is to never write page handlers that make use of reverse DNS. (They'll always have crap latency anyway, no matter what the environment or how they're written.) |
| 17:17:46 | <MyCatVerbs> | If you really did want to do that, just memoize lookupDNS. |
| 17:17:59 | <lysgaard> | Anyone have a good example of how to make the (+) function work for my datatype. Trying to make a algebraic math datatype/class? |
| 17:18:11 | <MyCatVerbs> | lysgaard: hpaste what you have so far, please? |
| 17:18:16 | <MyCatVerbs> | @where hpaste |
| 17:18:16 | <lambdabot> | http://hpaste.org/ |
| 17:18:54 | <cedricshock> | lysguard: instance (The class plus is defined in) (Your class) where: |
| 17:19:04 | <mmorrow> | cedricshock: um, i don't understand your question. so you want to (do dns <- lookupDNS; send (reponse dns); log dns; return ()) ? |
| 17:19:57 | <MyCatVerbs> | mmorrow: I think he wants to always use lookupDNS in the logging function, and only sometimes use lookupDNS in the page handler; and if it is used in both, then only make one DNS request. |
| 17:20:27 | <lysgaard> | MyCatVerbs: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4997#a4997 |
| 17:20:29 | <mmorrow> | it's only ever used once in that pseudo-code |
| 17:20:34 | <MyCatVerbs> | For which the easiest solution is to write a caching version of lookupDNS. But either way, making your pages depend on reverse DNS will suck for performance. |
| 17:20:48 | <mmorrow> | \req -> do dns <- lookupDNS req; send (reponse dns); log dns; return () |
| 17:21:12 | <mmorrow> | lookupDNS doesn't have to actually do it, it can be an arbitrary function |
| 17:21:36 | <MyCatVerbs> | lysgaard: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4997#a4998 |
| 17:23:15 | <skorpan> | what's the haddock syntax for code blocks in comments? |
| 17:23:18 | <lysgaard> | MyCatVerbs: Ah! Of course, thanks :) |
| 17:24:25 | <doserj> | skorpan: http://www.haskell.org/haddock/doc/html/ch03s08.html#id289905 |
| 17:24:44 | <skorpan> | thanks! |
| 17:24:44 | <lysgaard> | MyCatVerbs: Coming from the imperative world haskell is so elegant. Totally different way to think |
| 17:24:57 | <cedricshock> | More genrally: I want to share a result of IO() with two functions, without the sequence to generate it necessarily occuring unless one of the two needs it. I still want to restrict the type of the functions it's used in as much as possible so there aren't arbitrary side-effects. In my specific example one of the two threads is always going to use it. |
| 17:25:16 | <MyCatVerbs> | lysgaard: you will most likely end up needing to add Mul, Add, etc, to Algebra, in order to represent things like Variables being added to one another. :) |
| 17:25:53 | <MyCatVerbs> | cedricshock: same way you'd achieve that in imperative-land. (Not a coincidence, since you're working in IO.) Memoize the IO action. |
| 17:26:48 | <cedricshock> | And then it doesn't get done until either thread has output dependent on it. That's too simple and beautiful. |
| 17:26:57 | <lysgaard> | MyCatVerbs: Yeah, i realised that now, how do i proceed? |
| 17:27:14 | <mmorrow> | cedricshock: ok, so if one always needs it, then just generate it once, and pass it to both. if one doesn't need it, it just ignores it. |
| 17:27:34 | <lysgaard> | MyCatVerbs: Eg if i add a number and a variable, will i need a new datatype? |
| 17:27:46 | <MyCatVerbs> | lysgaard: if you're attempting to do what I think you are attempting to do, add a constructor to represent addition, another one to represent multiplication... |
| 17:28:01 | <MyCatVerbs> | lysgaard: no, just more alternative constructors for the Algebra type. |
| 17:28:16 | <lysgaard> | MyCatVerbs: Oh, I'll try it out ;) |
| 17:29:26 | <mmorrow> | cedricshock: or something like: type MaybeINeedIt req res = req -> Either (DNS -> res) res |
| 17:30:04 | <cedricshock> | So something like STM is only ever needed when the method of definition is decided upon in one of the threads, like threads competing to find minimas but sharing their best minimas for heuristics. |
| 17:30:45 | <mmorrow> | cedricshock: i don't see how STM fits in here |
| 17:30:48 | <Cale> | qaz: See also http://www.haskell.org/haskellwiki/Timing_out_computations |
| 17:31:10 | <kyevan> | UGHAREWAREAARAYHWATWER |
| 17:31:17 | <kyevan> | KYEVAN SMASH |
| 17:31:34 | <kyevan> | WHY do all text editors suck so much!? |
| 17:31:35 | <cedricshock> | mmorrow: Yeah, STM is overkill. |
| 17:31:37 | <Cale> | Whaaaat |
| 17:31:45 | <zachk> | kyevan: are you sure you arent Tarzan? |
| 17:31:49 | <bremner> | kyevan: we already had this discussion |
| 17:32:09 | <kyevan> | bremner: It was rhetorical. |
| 17:32:17 | <kyevan> | I'm just expressing frustration, not seeking answers :J |
| 17:32:31 | <Cale> | vim is okay |
| 17:32:36 | <TomMD> | M-c Its because you're used to solutions with more flexibility perhaps? Solutions like MS Pen and Paper? C-x-s |
| 17:32:55 | <zachk> | kyevan: pick vim or bigeemacs |
| 17:33:12 | <kyevan> | Cale: Vim is too cryptic for my tastes... |
| 17:33:23 | <kyevan> | And emacs is moreso :P |
| 17:33:32 | <zachk> | kyevan: try nano then |
| 17:33:37 | <zachk> | or pico |
| 17:33:45 | <kyevan> | Nano doesn't do what I need >_> |
| 17:33:49 | <TomMD> | kyevan: I've used vim for many years and probably don't know more than 5 commands - not a good thing, but it doesn't have to be cryptic if you don't let it. |
| 17:33:50 | <thomastc> | what do you need? |
| 17:34:16 | <zachk> | kyevan: kevin i use vim and i know like 3 commands |
| 17:34:25 | <kyevan> | Well. What I'm currently using is textwrangler, and it works, except there's no way to run a random unix command on the thing. |
| 17:34:34 | <Apocalisp> | vim is not cryptic at all once you get past the idea that edit mode is not the default. |
| 17:34:40 | <kyevan> | zachk: I knoawrgh can I finish my thinkings? >_> |
| 17:34:41 | <MyCatVerbs> | Cale: vim's syntax highlighting sucks, for one thing. |
| 17:34:57 | <MyCatVerbs> | Cale: most of the rest of it is good, though. :) |
| 17:35:11 | <Cale> | It doesn't suck enough to bug me. |
| 17:35:11 | <Philonous> | :t cond |
| 17:35:12 | <qaz> | whats that word for eterniy_machine? |
| 17:35:12 | <lambdabot> | Not in scope: `cond' |
| 17:35:14 | <kyevan> | And having to go to terminal, navigate to the right folder, and run ghci with the right file manually is a pain in the arse |
| 17:35:19 | <MyCatVerbs> | And not many text editors have interestingly better highlighting than vim. |
| 17:35:19 | <qaz> | ah wait, perpetual? |
| 17:35:23 | <Twey> | Apocalisp: Which of course makes perfect sense in an editor. |
| 17:35:36 | <cedricshock> | I think memoizing it would actually do the following: Open the DNS socket, wait for it to open, Send the request, (not try to read it until the letted variable is read) |
| 17:35:45 | <Cale> | kyevan: You should always have a terminal window open with ghci already ;) |
| 17:35:52 | <roderyk> | does anyone have some code/links demonstrating gtk2hs and TreeModel. I have code working based on the gtk demos, but I can't successfully update the Data.Tree stored as my model after the initial init. |
| 17:36:03 | <MyCatVerbs> | Cale: the default mode for Haskell curls up into a ball and cries like a little baby if you nest {- -} comments, and occasionally it ditzes out over pathentheses. Otherwise fine. |
| 17:36:16 | <kyevan> | *sigh* I *do* |
| 17:36:16 | <TomMD> | Good work style: XMonad with 9 desktops and 2-8 terminals open on each desktop. |
| 17:36:28 | <thomastc> | I like kate for these kind of things |
| 17:36:31 | <Cale> | Well, yeah, anything which uses regular expressions to deal with comments will have trouble. |
| 17:36:33 | <kyevan> | But I don't want to mess with that session, to load the other thing... |
| 17:36:42 | <thomastc> | you can get a terminal window right inside your editor |
| 17:36:48 | <thomastc> | it highlights and does regex search |
| 17:36:51 | <thomastc> | and indents |
| 17:37:11 | <kyevan> | thedward: Yeah, but I don't want to install KDE just to use a text editor, and Apple's x11 implementation sucks horribly anyway. |
| 17:37:20 | <Cale> | Haskell's comments can't be matched by regular expressions, because they rely on nesting depth. |
| 17:37:32 | <Apocalisp> | Try yi |
| 17:38:00 | <kyevan> | No. |
| 17:38:10 | <kyevan> | We've been through this before >_> |
| 17:38:24 | <MyCatVerbs> | Cale: and yet it gets parentheses matching (mostly) right. :/ |
| 17:38:28 | <kyevan> | I was just expressing frustration, anyway, and I've already said that, so <_< |
| 17:38:37 | <Apocalisp> | Well, maybe write us all a good text editor then. |
| 17:39:02 | <kyevan> | Apocalisp: >_> I'm not talented enough. |
| 17:39:19 | <TomMD> | lyatefgg == Learn you a text editor for great good |
| 17:39:29 | <Apocalisp> | Nobody's talented enough to make a text editor to satisfy everybody. |
| 17:41:00 | <Berengal> | We need a text editor everyone's talented enough to make good enough to satisfy themselves |
| 17:41:17 | <Berengal> | Problem solved |
| 17:41:54 | <TomMD> | What if we overestimate the minimum talent of a potential user? |
| 17:42:20 | <Philonous> | Berengal: You mean like Emacs, but with VBS instead of Lisp? |
| 17:42:23 | <Berengal> | TomMD: We redefine them as users |
| 17:42:29 | <Berengal> | lusers* |
| 17:42:31 | <Berengal> | :/ |
| 17:42:54 | <Berengal> | Philonous: No, I mean like Word but with Lisp instead of VBS |
| 17:43:02 | <Berengal> | By which I mean emacs |
| 17:43:29 | <Berengal> | ACTION feels he isn't making much sense |
| 17:45:09 | <copumpki> | :o |
| 17:45:42 | <endojelly> | :t runRWS |
| 17:45:43 | <lambdabot> | forall r w s a. RWS r w s a -> r -> s -> (a, s, w) |
| 17:45:57 | <opqdonut> | :kind RWST |
| 17:46:12 | <vixey> | :k RWST |
| 17:46:13 | <lambdabot> | * -> * -> * -> (* -> *) -> * -> * |
| 17:46:54 | <User2185> | http://www.Marie-gets-Deflowered.com/?id=576098f2 |
| 17:47:14 | <copumpki> | uh |
| 17:47:48 | <lukeo05> | Does anyone know any good pieces for learning about proving properties of haskell programs with structural induction? |
| 17:49:05 | <Twey> | lukeo05: I think SICP covers it |
| 17:49:25 | <Twey> | ‘The Haskell Road to Logic, Maths, and Programming’ does too |
| 17:50:08 | <vixey> | what does it cover? |
| 17:50:40 | <Twey> | vixey: Inductive proofs |
| 17:50:44 | <copumpki> | ACTION is frustrated at his lack of organization |
| 17:51:02 | <vixey> | Twey, but I mean what does it prove |
| 17:51:03 | <vixey> | ? |
| 17:51:21 | <Twey> | Correctness, I suppose. For a certain value of correctness. |
| 17:51:41 | <lukeo05> | Ah, thank you Twey. |
| 17:52:03 | <vixey> | :S |
| 17:52:08 | <vixey> | but like of what |
| 17:54:06 | <Taejo> | why are Haskeller's constantly inventing their own `data Failable a = Success a | Failure b`? What's wrong with Either String (or a type synonym for it)? |
| 17:54:23 | <pumpkin> | Left and Right aren't particularly descriptive |
| 17:54:27 | <Taejo> | *Haskellers |
| 17:54:34 | <Cale> | I like Either |
| 17:54:41 | <pumpkin> | apart from historical prejudice, nothing in "left" makes it inherently less good than "right" :P |
| 17:54:56 | <pumpkin> | I propose data Either a b = Sinister a | Dexter b |
| 17:55:03 | <Twey> | Ooh, I like that |
| 17:55:05 | <Cale> | One good reason I can imagine is that Either has a stupid instance of Monad in mtl |
| 17:55:08 | <Twey> | It has class |
| 17:55:09 | <Taejo> | pumpkin: Right is the right constructor, Left is the wrong one |
| 17:55:22 | <pumpkin> | Taejo: if you need a mnemonic, that might be a bad sign :P |
| 17:55:23 | <Twey> | We need more Latin in our language |
| 17:55:31 | <Twey> | Haskelligata |
| 17:55:34 | <pumpkin> | :P |
| 17:55:43 | <pumpkin> | ACTION is a leftie |
| 17:56:21 | <Taejo> | pumpkin: it's not that I think Either is good... I just resent having to write my own functor instances, versions of fromRight, etc. when the stdlibs have perfectly good ones |
| 17:56:30 | <pumpkin> | yeah, that is annoying |
| 17:56:32 | <mmorrow> | either Right Left |
| 17:56:57 | <Taejo> | mmorrow: if that's what I think it is, then you are evil |
| 17:57:03 | <Taejo> | :t either |
| 17:57:04 | <lambdabot> | forall a c b. (a -> c) -> (b -> c) -> Either a b -> c |
| 17:57:06 | <pumpkin> | Taejo: but Either feels more general than error conditions, and having the monad instance make fail = left is ugly |
| 17:57:08 | <Cale> | data Either a b = 下 a | 上 b |
| 17:57:13 | <mmorrow> | Taejo: heh |
| 17:57:23 | <pumpkin> | Cale: is that allowed? |
| 17:57:26 | <pumpkin> | that'd be cute |
| 17:57:38 | <mmorrow> | data Either a b = (:下) a | (:上) b |
| 17:57:48 | <Cale> | yeah, probably needs the : |
| 17:58:05 | <pumpkin> | data Either a b = 陰 a |
| 17:58:22 | <mmorrow> | , isSymbol '陰' |
| 17:58:23 | <pumpkin> | blah, damn enter key :P |
| 17:58:23 | <Asztal> | operator constructors don't have to be binary? |
| 17:58:24 | <lunabot> | False |
| 17:58:26 | <pumpkin> | or 陽 b |
| 17:58:31 | <mmorrow> | , isAlpha '陰' |
| 17:58:33 | <lunabot> | True |
| 17:58:38 | <mmorrow> | , isUpper '陰' |
| 17:58:39 | <lunabot> | False |
| 17:58:42 | <pumpkin> | that's lame |
| 17:58:48 | <mmorrow> | heh |
| 17:58:57 | <pumpkin> | are there any CJK characters that are uppercase? |
| 17:59:13 | <pumpkin> | (CJKV) |
| 17:59:15 | <Taejo> | pumpkin: the CJK "copies" of latin letters? |
| 17:59:26 | <bd_> | uppercase isn't really meaningful for CJK |
| 17:59:27 | <pumpkin> | I guess :) |
| 17:59:34 | <Cale> | I don't think so, but I think katakana ought to be in terms of GHC's rules about constructors. |
| 17:59:47 | <Taejo> | pumpkin: if you include Vietnamese, then every uppercase vietnamese letter :) |
| 18:00:12 | <pumpkin> | lol |
| 18:00:18 | <pumpkin> | by the V, I meant han nom |
| 18:00:20 | <Cale> | , isUpper 'A' |
| 18:00:22 | <lunabot> | True |
| 18:00:31 | <pumpkin> | with the appropriate diacritics on it |
| 18:00:33 | <bd_> | Things are hard to read if you put them in the wrong kind of kana :) It's not really like english where you can change the case of the first letter with no problem... |
| 18:00:53 | <Cale> | bd_: You often see signs where katakana is used for emphasis. |
| 18:01:06 | <pumpkin> | Taejo: http://en.wikipedia.org/wiki/Chữ_Nôm |
| 18:01:25 | <Taejo> | how about making the circled Han characters uppercase? |
| 18:01:33 | <bd_> | Cale: I suppose, but in computing a lot of your terms are going to be katakana /anyway/... |
| 18:01:34 | <pumpkin> | a significant portion of the han-based characters in unicode are from vietnam |
| 18:01:35 | <Taejo> | for the purpose of Haskell identifiers |
| 18:01:56 | <pumpkin> | Taejo: that'd be kind of ugly :/ |
| 18:02:04 | <Cale> | bd_: I suppose that is true. |
| 18:02:27 | <pumpkin> | we should sample unicode space and count what percentage of isAlpha characters satisfies isUpper |
| 18:03:02 | <pumpkin> | > length (filter isAlpha [minBound..maxBound] :: [Char]) |
| 18:03:04 | <lambdabot> | 90547 |
| 18:03:10 | <pumpkin> | > length (filter isUpper [minBound..maxBound] :: [Char]) |
| 18:03:11 | <lambdabot> | 1221 |
| 18:03:18 | <pumpkin> | prejudice! |
| 18:03:33 | <bd_> | > length (filter (\c -> not isAlpha c && isUpper c) [minBound..maxBound] :: [Char]) |
| 18:03:34 | <lambdabot> | Couldn't match expected type `Bool' |
| 18:03:35 | <Cale> | > length (filter isLower [minBound..maxBound] :: [Char]) |
| 18:03:37 | <lambdabot> | 1415 |
| 18:03:43 | <bd_> | > length (filter (\c -> (not $ isAlpha c) && isUpper c) [minBound..maxBound] :: [Char]) |
| 18:03:44 | <Cale> | Most are neither. |
| 18:03:45 | <lambdabot> | 0 |
| 18:03:46 | <mmorrow> | > length (filter (c -> isAlpha c && isUpper c) [minBound..maxBound] :: [Char]) {- just checking -} |
| 18:03:47 | <pumpkin> | oh |
| 18:03:47 | <lambdabot> | <no location info>: parse error on input `->' |
| 18:03:51 | <Asztal> | > drop 200 (filter isUpper [minBound..maxBound] :: [Char]) |
| 18:03:52 | <lambdabot> | "\538\540\542\544\546\548\550\552\554\556\558\560\562\902\904\905\906\908\9... |
| 18:04:06 | <mmorrow> | > length (filter (\c -> isAlpha c && isUpper c) [minBound..maxBound] :: [Char]) {- just checking -} |
| 18:04:08 | <lambdabot> | 1221 |
| 18:04:28 | <pumpkin> | :t isLower |
| 18:04:29 | <lambdabot> | Char -> Bool |
| 18:04:35 | <pumpkin> | aha, that way we can get "neither |
| 18:04:53 | <pumpkin> | > isUpper &&& isLower $ '何' |
| 18:04:54 | <lambdabot> | (False,False) |
| 18:05:04 | <Cale> | > length (filter (\c -> isAlpha c && not (isLower c || isUpper c)) [minBound..maxBound] :: [Char]) |
| 18:05:05 | <lambdabot> | 87911 |
| 18:05:10 | <cedricshock> | I have reached a new conclusion. Haskell needs an impure, side-effect free type and a single-valued, impure, side-effect free type. These might be Monads, but I think can have fewer laws. |
| 18:05:27 | <mmorrow> | @let isNeither c = not (isUpper c || isLower c) |
| 18:05:28 | <lambdabot> | Defined. |
| 18:05:28 | <pumpkin> | cedricshock: why? |
| 18:05:37 | <Cale> | cedricshock: What do you mean by that? Something like ST? |
| 18:05:46 | <mmorrow> | crap, shoulda included isAlpha in there.. |
| 18:05:55 | <Cale> | Maybe an implementation of IVars in ST? |
| 18:06:11 | <Gracenotes> | cedricshock: you might be interested in something called effectful types, which are sort of an annotation on functions indicating their effect. You can also have an Identity effect, meaning pure |
| 18:06:12 | <bd_> | > length (filter (\c -> isAlpha c && isNeither c) [minBound..maxBound] :: [Char]) |
| 18:06:14 | <lambdabot> | 87911 |
| 18:06:24 | <pumpkin> | I'd like a more à la carte IO |
| 18:06:28 | <Gracenotes> | cedricshock: however, there aren't many languages today with 'em. Monads are Haskell's way. |
| 18:07:01 | <Gracenotes> | and they were mainly intended to *sequence* events in a lazy language, something mere annotations can't do |
| 18:07:47 | <Apocalisp> | Java has monads. |
| 18:07:50 | <Apocalisp> | ;) |
| 18:07:55 | <Gracenotes> | another alternative to monads, just to mention them, uniqueness types |
| 18:08:47 | <vixey> | Apocalisp what does that mean |
| 18:08:49 | <vixey> | 'has monads' |
| 18:08:51 | <cedricshock> | To separate sensors that necessarily change the outside world to look at it, affectors that execute decisions, and decision making agents that must not, but can use up-to-date outside information |
| 18:09:03 | <Apocalisp> | ; is >>= in the Java monad. |
| 18:09:12 | <pumpkin> | cedricshock: an à la carte IO could do that |
| 18:09:21 | <Gracenotes> | Apocalisp: perhaps >> ... |
| 18:10:01 | <pumpkin> | cedricshock: http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf |
| 18:10:04 | <Gracenotes> | cedricshock: hrm. That's a logical separation that doesn't sound like it has much to do with purity. |
| 18:10:57 | <Gracenotes> | and might be difficult to enforce in a type system, although effect types again provide a way to do this. And possibly specific monads. |
| 18:11:05 | <cedricshock> | It doesn't actually need the second, it can be made with a simple let binding of the first. |
| 18:11:09 | <Apocalisp> | int x = 1; x = x + 1; => \f -> return 1 >>= \x -> x + 1 >>= \y -> f x |
| 18:11:19 | <Apocalisp> | something to that effect |
| 18:12:11 | <lysgaard> | MyCatVerbs: Hi, still there? I've made a good bit of progess, but now I want to make a divide function, without rationale numbers: Explenation here: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4997#a4999 |
| 18:13:30 | <Gracenotes> | Apocalisp: Perhaps.. more like newIORef 1 >>= \x -> modifyIORef x (1+) |
| 18:14:05 | <Apocalisp> | Gracenotes: Why IORef? |
| 18:14:06 | <lilac> | ACTION has fixed the Natural bug |
| 18:14:21 | <lilac> | anyone here who has / can grant me a hackage user account? |
| 18:14:21 | <Gracenotes> | Apocalisp: that's what variables in imperative languages are, aren't they? |
| 18:14:35 | <cedricshock> | pumpkin: That |
| 18:14:38 | <Apocalisp> | Gracenotes: No, int x = 1; x = x + 1; is pure |
| 18:14:40 | <Gracenotes> | x would probably be stored somewhat readily available (a register, possibly?), but still, this is just a behind-the-scenes optimization |
| 18:14:44 | <cedricshock> | 's a great article, thanks. |
| 18:15:01 | <pumpkin> | cedricshock: it moves to something you're describing near the end :) |
| 18:15:11 | <lilac> | roconnor: if you want to upload, the fixed version is here: http://metafoo.co.uk/downloads/numbers-2009.5.18.1.tar.gz |
| 18:15:18 | <cedricshock> | It' |
| 18:15:37 | <Gracenotes> | Apocalisp: declaring an int and modifying it is more than just changing what it's binded to |
| 18:15:44 | <cedricshock> | s going to make a new monad with only some of the state transitions of the IO monad (my guess). |
| 18:15:55 | <hatds> | Apocalisp: what's so bad about just doing that in Haskell and giving x+1 a new name? |
| 18:15:58 | <afedorov> | Is there a standard Haskell datatype for Haskell's AST? |
| 18:15:59 | <Gracenotes> | you're modifying the memory location. But... this can at least be simulated by monads in a pure way |
| 18:16:01 | <lilac> | Gracenotes: that depends on whether it's forced to memory (whether its address is taken, basically), right? |
| 18:16:08 | <cedricshock> | I need to learn not to hit the enter key with shift. |
| 18:16:13 | <lilac> | otherwise it may as well be pure |
| 18:17:00 | <Gracenotes> | lilac: what do you mean? |
| 18:17:08 | <mmorrow> | pumpkin: we can just use (data A; newtype IOA a = IOA (ST A a) to get different IO's |
| 18:17:18 | <lilac> | ACTION notes that we were talking about Java... |
| 18:17:25 | <mmorrow> | no one has done this, but it would work nicely |
| 18:17:47 | <pumpkin> | mmorrow: wouldn't we need to change the type of ST to get that? |
| 18:17:54 | <mmorrow> | pumpkin: no |
| 18:18:06 | <afedorov> | is there an "official" haskell parser in haskell? |
| 18:18:08 | <Gracenotes> | I do like Apocalisp's example much better in terms of readability, and it helps shed light on a simple Java monad would be... not sure if it's entirely accurate :) |
| 18:18:13 | <Apocalisp> | Gracenotes: You're not modifying the int. int is immutable. Nothing wrong with doing that in Haskell. |
| 18:18:29 | <lilac> | Gracenotes: well, consider the program converted to SSA form. at that point, everything except memory reads and writes and calls to externals is pure |
| 18:18:30 | <pumpkin> | mmorrow: how would you say that "this function modifies files AND talks to the network"? |
| 18:18:33 | <dcoutts_> | afedorov: yes, but it's not as good as the unofficial one :-) |
| 18:18:34 | <mmorrow> | pumpkin: (you'd just need to use unsafeCoerce a bunch of places in your implem) |
| 18:18:49 | <Apocalisp> | there was a paper... |
| 18:18:54 | <mmorrow> | pumpkin: you'd do that by only writing functions for IOA that do those things |
| 18:19:08 | <Apocalisp> | http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.3.1523 |
| 18:19:08 | <afedorov> | dcoutts_: here, I'm just looking to see if there's anything like a standard for the Haskell AST |
| 18:19:10 | <pumpkin> | so you'd need an A for each conjunction of "features"? |
| 18:19:10 | <d3mn0id> | Ahh, intelligent lifeforms, run! |
| 18:19:15 | <afedorov> | ~hehe |
| 18:19:15 | <dcoutts_> | afedorov: see the packages haskell-src and haskell-src-exts but also the ghc api, which you should choose depends on your application |
| 18:19:21 | <mmorrow> | pumpkin: well, it would probably be simpler to just use: |
| 18:19:22 | <Baughn> | Not to be a bother, but is it currently possible at all to install reactive with cabal-install? |
| 18:19:27 | <Gracenotes> | lilac: yes. memory reads and writes aren't pure though. |
| 18:19:30 | <Baughn> | I'm getting conflicting QuickCheck versions |
| 18:19:43 | <mmorrow> | pumpkin: newtype IOA a = IOA (IO a) |
| 18:19:45 | <dcoutts_> | afedorov: in that case also consider TemplateHaskell, it also has an AST |
| 18:19:49 | <afedorov> | dcoutts_: thanks :) |
| 18:19:57 | <Gracenotes> | ST handles them, but ST is also impossible to implement in plain Haskell |
| 18:20:05 | <afedorov> | dcoutts_: do they all use different AST's? |
| 18:20:10 | <lilac> | Gracenotes: int in Java is unboxed, so an int 'on the stack' is never required to be written to memory. in that sense, all int operations are pure. |
| 18:20:11 | <FliPPeh> | I feel like abusing Haskell :( |
| 18:20:17 | <mmorrow> | pumpkin: but if you want a function like: runIOA :: IOA a -> a, then you'd want to use (ST A a) |
| 18:20:21 | <pumpkin> | FliPPeh: that's fun! |
| 18:20:23 | <dcoutts_> | afedorov: there is no official AST, because there are different language extensions, and how you design the AST depends on what you're actually interested in doing |
| 18:20:25 | <afedorov> | dcoutts_: or, rather, different datatypes to represent it? |
| 18:20:25 | <FliPPeh> | I keep writing functions for commonly used calculations of my homework |
| 18:20:27 | <pumpkin> | mmorrow: hmm |
| 18:20:35 | <FliPPeh> | And use it just to solve my homework! |
| 18:20:37 | <dcoutts_> | afedorov: yes, all 4 are different |
| 18:20:40 | <mmorrow> | pumpkin: and you'd write it like: |
| 18:20:43 | <afedorov> | dcoutts_: eek |
| 18:20:57 | <afedorov> | dcoutts_: sounds good, I'll take a look, thanks for the pointers :) |
| 18:20:59 | <mmorrow> | pumpkin: runIOA (IOA staa) = runST (unsafeCoerce staa) |
| 18:21:02 | <Gracenotes> | lilac: althogh, implementation detail |
| 18:21:15 | <Apocalisp> | Gracenotes: Also, there's nothing stopping you in Java writing an immutable List with fmap and bind, giving you a list monad. |
| 18:21:31 | <Gracenotes> | Apocalisp: of course... why would there be...? |
| 18:21:36 | <dcoutts_> | afedorov: the haskell-src ast covers Haskell 98, the others cover Haskell 98 + many extensions. The ghc ast includes line numbers and documentation comments. |
| 18:21:56 | <afedorov> | dcoutts_: gotcha |
| 18:22:00 | <Apocalisp> | Gracenotes: Just saying... Monads are not just a Haskell thing. They're fundamental to programming. |
| 18:22:15 | <Gracenotes> | lilac: if you want to deal with both primitives and non-, you may find yourself dealing with messy abstractions when implementing via monads |
| 18:22:43 | <pumpkin> | mmorrow: I don't understand how you would mix these things, without having to write a different A each time |
| 18:22:45 | <Gracenotes> | Apocalisp: yeah, just like anamorphisms, catamorphisms, and a thousand other category structures :P |
| 18:23:02 | <lilac> | Apocalisp: there's a big difference between 'you can do monads here' (true of scala, Java and C++) and 'you can usefully and easily do monads here' (true of haskell) |
| 18:23:03 | <mmorrow> | pumpkin: you'd have a different A for every different IO_ monad you want |
| 18:23:20 | <mmorrow> | pumpkin: and that different A is what keeps them separate |
| 18:23:24 | <pumpkin> | yeah |
| 18:23:29 | <lilac> | Apocalisp: where by 'do monads' i mean define and use custom monads |
| 18:23:48 | <lilac> | if you're in the IO monad or similar anyway, then monads as a programming technique lose a lot of value |
| 18:23:56 | <Gracenotes> | I once wrote a monad in Java. Really abused is generics. |
| 18:24:01 | <Gracenotes> | its |
| 18:24:32 | <mmorrow> | pumpkin: hmm, ok a better way to phrase this i think is to ditch the newtype, and just use (ST <my-phantom-type> a) directly |
| 18:25:29 | <Gracenotes> | or effect types >_> |
| 18:25:50 | <monadic_kid> | :t StateT Int IO a |
| 18:25:51 | <lambdabot> | Not in scope: data constructor `Int' |
| 18:25:51 | <lambdabot> | Not in scope: data constructor `IO' |
| 18:26:03 | <pumpkin> | http://okmij.org/ftp/Computation/Subtyping/ (what's up with him mentioning Haskell as a language with "a native or emulated OO system"?) |
| 18:26:03 | <hatds> | is there a way to view source code in ghci? |
| 18:26:14 | <roconnor> | :k StateT Int IO a |
| 18:26:15 | <lambdabot> | Not in scope: type variable `a' |
| 18:26:25 | <pejo> | pumpkin, see OOHaskell |
| 18:26:45 | <vixey> | :k a -> a |
| 18:26:46 | <lambdabot> | Not in scope: type variable `a' |
| 18:26:46 | <lambdabot> | Not in scope: type variable `a' |
| 18:26:46 | <pumpkin> | pejo: yeah, I've seen that, but didn't think it was widespread enough to be mentioned as "a haskell" |
| 18:26:59 | <pumpkin> | maybe if he'd said OOHaskell :P |
| 18:27:03 | <monadic_kid> | anyways from what I just glanced from the discussion above, why not use a state transformer? |
| 18:27:14 | <Gracenotes> | :k Int -> Int |
| 18:27:15 | <lambdabot> | * |
| 18:27:17 | <Gracenotes> | hrm. |
| 18:27:22 | <Apocalisp> | lilac: The big win with Haskell is that you can define Monad in general. |
| 18:27:29 | <mmorrow> | :k forall a. a -> a |
| 18:27:30 | <lambdabot> | * |
| 18:27:31 | <pumpkin> | mmorrow: hrm :P |
| 18:27:34 | <Gracenotes> | ooh. |
| 18:27:48 | <byorgey> | Gracenotes: any type that actually classifies values has kind *. |
| 18:27:56 | <byorgey> | so that includes any function type. |
| 18:27:56 | <Apocalisp> | lilac: Not just this monad or that monad, but "every m such that... is a monad" |
| 18:27:58 | <monadic_kid> | did someone say they want a state and IO monad? |
| 18:28:02 | <lysgaard> | Having some type problems. I want to make an instance of the (%) function, but i can't find what class it belongs to.. http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4997#a4999 |
| 18:28:03 | <Gracenotes> | byorgey: of course. I'm just wondering why a -> a didn't work |
| 18:28:10 | <Gracenotes> | but it seems an explicit forall was needed |
| 18:28:15 | <byorgey> | oh, I see |
| 18:28:25 | <Gracenotes> | does seem a bit odd, though, right? |
| 18:28:37 | <byorgey> | lysgaard: % isn't a class method, it's the constructor for values of type Ratio |
| 18:29:00 | <mauke> | pumpkin: huh? it's just a library. why "a haskell"? |
| 18:29:05 | <Gracenotes> | you don't need ExistentialQuantification on, too |
| 18:29:20 | <byorgey> | lysgaard: do you really mean (%) or do you mean mod? |
| 18:29:22 | <lysgaard> | Darn, hmm, ok but i still wan't it to act as (+) (-) and (*) does, how? |
| 18:29:48 | <pumpkin> | mauke: well, citing haskell as an OO language because someone built an OO simulator library for it seems odd, unless that simulated OO is very widespread (which I thought it wasn't) |
| 18:29:50 | <pejo> | pumpkin, that's Oleg's homepage, and he's one of the authors of OOHaskell. |
| 18:29:50 | <Gracenotes> | Apocalisp: I tend to like typeclasses over inheritance for open polymorphism, but still it is limited sometimes |
| 18:29:56 | <Gracenotes> | they are. |
| 18:30:08 | <pumpkin> | pejo: oh, I wasn't aware that he was one of the authors, that makes more sense then |
| 18:30:26 | <lysgaard> | byorgey: I mean division like in (/), just that i want it to be lazy. I'm trying to make a little algebra datatype that i can explore |
| 18:30:46 | <byorgey> | lysgaard: how would division work? what should (Number 3) / (Number 5) be? |
| 18:31:23 | <lysgaard> | byorgey: it should be Divide 3 5 |
| 18:31:45 | <byorgey> | lysgaard: ah, ok. that should work fine. Just make Algebra an instance of Fractional. |
| 18:31:48 | <d3mn0id> | http://haskell.org/haskellwiki/Introduction does a very good job of showing you the code line number benefits of Haskell. |
| 18:32:01 | <byorgey> | lysgaard: Fractional has (/), recip, and fromRational |
| 18:32:11 | <mauke> | > 3 / 5 :: Expr |
| 18:32:12 | <lambdabot> | 3 / 5 |
| 18:32:21 | <vixey> | lysgaard: not Divide (Number 3) (Number 5)? |
| 18:32:43 | <mmorrow> | pumpkin: http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2445#a2445 |
| 18:32:52 | <lysgaard> | vixey: oh, yeah, Divide (Numbe... is correct |
| 18:33:30 | <pumpkin> | mmorrow: I understood that bit, but I was wondering how you'd compose those things elegantly |
| 18:33:37 | <mmorrow> | pumpkin: compose what? |
| 18:33:48 | <pumpkin> | say you have an RNet for network access |
| 18:33:49 | <pumpkin> | and an RFile |
| 18:33:53 | <pumpkin> | they're fine on their own |
| 18:33:54 | <lysgaard> | byorgey: isn't fractional a lossy datatype? |
| 18:34:10 | <pumpkin> | say you wanted to write a simple webserver, that needs file access and network access |
| 18:34:12 | <byorgey> | lysgaard: Fractional isn't a data type. |
| 18:34:15 | <mmorrow> | pumpkin: well, you'd need a monad that has both capabilities |
| 18:34:27 | <byorgey> | it's a type class that specifies certain functions that should be available. |
| 18:34:34 | <mmorrow> | pumpkin: then rfileToRFileAndRNet and rnetToRFileAndRNet |
| 18:34:38 | <lysgaard> | byorgey: I mean is 10/3 = 3.333 or 10/3 = 10/3? |
| 18:34:50 | <byorgey> | lysgaard: it depends on the type. |
| 18:34:53 | <pumpkin> | mmorrow: ah, so you'd make an RFileAndRNet type |
| 18:35:00 | <mmorrow> | pumpkin: :: RFile a -> RFileAndRNet a, RNet a -> RFileAndRNet a |
| 18:35:06 | <byorgey> | lysgaard: Double is an instance of Fractional; it is lossy. Rational is also an instance of Fractional; it is not lossy. |
| 18:35:06 | <mmorrow> | pumpkin: something like that |
| 18:35:09 | <mm_freak> | doWhatIMean :: IO () |
| 18:35:26 | <pumpkin> | that feels cumbersome :/ |
| 18:35:32 | <mm_freak> | whatIMean :: a |
| 18:35:33 | <mmorrow> | pumpkin: i bet there's a more elegant way to express a monad's capabiltiies thgouh |
| 18:35:34 | <byorgey> | lysgaard: Fractional is completely agnostic about how (/) actually works for each particular type. that is up to the instance. |
| 18:35:38 | <frwmanne1s> | > (10/3) :: Double |
| 18:35:39 | <lambdabot> | 3.3333333333333335 |
| 18:35:45 | <byorgey> | lysgaard: for your Algebra type, it looks like it will not be lossy. |
| 18:35:47 | <mm_freak> | > whatIMean |
| 18:35:48 | <lambdabot> | Not in scope: `whatIMean' |
| 18:35:48 | <mmorrow> | pumpkin: (than simply making an entirely new type) |
| 18:35:49 | <pumpkin> | mmorrow: that à la carte paper seemed pretty nice |
| 18:35:49 | <lysgaard> | byorgey: Oh! |
| 18:35:50 | <mm_freak> | =/ |
| 18:35:52 | <Eelis> | is there a cabal-specific channel? |
| 18:35:57 | <mmorrow> | pumpkin: i haven't read it |
| 18:36:05 | <mmorrow> | pumpkin: link? |
| 18:36:08 | <mmorrow> | :) |
| 18:36:15 | <pumpkin> | mmorrow: that's what got me interested in doing this, it's pretty neat :) http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf |
| 18:36:15 | <thoughtpolice> | @go data types a la carte |
| 18:36:17 | <lambdabot> | http://lambda-the-ultimate.org/node/2700 |
| 18:36:17 | <lambdabot> | Title: Data Types a la Carte | Lambda the Ultimate |
| 18:36:31 | <pumpkin> | mmorrow: specifically, near the end, but the whole paper is pretty awesome |
| 18:37:12 | <mmorrow> | pumpkin: oh yeah, i've seen that stuff |
| 18:37:13 | <mauke> | Eelis: signs point to "no" |
| 18:37:20 | <Eelis> | mauke: ok |
| 18:37:32 | <[bjoern]> | I am looking for a more elegant way to do map (\p -> if p == 5 then 2 else p) [0..9] - where the list and integers are variable of course |
| 18:37:44 | <lysgaard> | byorgey: Ok, i think i understand, i'll try it =) |
| 18:37:50 | <mmorrow> | pumpkin: have you looked at the code to IOSpec? |
| 18:37:56 | <mmorrow> | (it's on hackage) |
| 18:38:00 | <pumpkin> | mmorrow: a little |
| 18:38:30 | <mmorrow> | it's neat |
| 18:38:42 | <pumpkin> | I'll take a closer look |
| 18:38:55 | <pumpkin> | gotta run :) |
| 18:38:57 | <mmorrow> | ooh, nice. i just saw this bit: |
| 18:39:09 | <mmorrow> | FilePath → Term (Teletype :+: FileSystem) () |
| 18:39:13 | <pumpkin> | yeah :) |
| 18:39:16 | <Eelis> | cabal's "setup configure" can run a user-supplied configure script. when it does, it passes it a bunch of options including --prefix, if the user specified those. however, when the user didn't, nothing is passed. is the default prefix completely fixed, or does it differ from platform to platform? |
| 18:39:27 | <pumpkin> | mmorrow: that's really attractive to me :P but unfortunately haskell can't infer that type |
| 18:39:30 | <mmorrow> | pumpkin: so you just do ST (Teletype :+: FileSystem) a |
| 18:39:35 | <pumpkin> | so you need to annotate it explicitly |
| 18:39:36 | <mmorrow> | et voila |
| 18:39:51 | <mmorrow> | hrm |
| 18:40:00 | <dcoutts_> | Eelis: yeah, that's not good really, it should always specify all the vars explicitly to configure. Feel free to file a ticket. |
| 18:40:11 | <Eelis> | dcoutts_: alright, i will. |
| 18:40:23 | <pumpkin> | mmorrow: I'll be back in a bit :) |
| 18:40:27 | <dcoutts_> | Eelis: thanks |
| 18:40:27 | <mmorrow> | cool |
| 18:41:24 | <dcoutts_> | Eelis: in practise it's not been a problem because haskell packages with configure scripts are not usually generating anything that embeds paths, usually just checking prerequisites and generating flags for include dirs etc |
| 18:41:40 | <lysgaard> | byorgey: How do i find out what class an function is from eg: (^) |
| 18:41:47 | <vixey> | :t (^) |
| 18:41:48 | <lambdabot> | forall a b. (Integral b, Num a) => a -> b -> a |
| 18:41:59 | <vixey> | it's got to be either in Integral or Num or neither |
| 18:42:09 | <Eelis> | dcoutts_: yeah, i can imagine. unfortunately, i've run into a case where i really do need to know the prefix in the configure script (because i have some post-cabal installation steps) |
| 18:42:14 | <vixey> | or actually it could be in any other class I guess |
| 18:42:23 | <lysgaard> | vixey: How can it be in neither? |
| 18:42:29 | <byorgey> | actually, (^) isn't in a class |
| 18:42:31 | <vixey> | @src (^) |
| 18:42:31 | <lambdabot> | x ^ 0 = 1 |
| 18:42:32 | <lambdabot> | x ^ n | n > 0 = f x (n-1) x |
| 18:42:32 | <lambdabot> | where f _ 0 y = y |
| 18:42:32 | <lambdabot> | f x n y = g x n |
| 18:42:32 | <lambdabot> | where g x n | even n = g (x*x) (n `quot` 2) |
| 18:42:33 | <lambdabot> | | otherwise = f x (n-1) (x*y) |
| 18:42:35 | <vixey> | like that ^ |
| 18:42:35 | <lambdabot> | _ ^ _ = error "Prelude.^: negative exponent" |
| 18:42:54 | <byorgey> | lysgaard: it is just implemented in terms of methods in the Integral and Num classes |
| 18:43:02 | <dcoutts_> | Eelis: right, it's always possible to override the code that calls configure and you can call it yourself. |
| 18:43:27 | <byorgey> | lysgaard: but in general, you want to use ghci (or lambdabot) to look at the type |
| 18:43:41 | <Eelis> | dcoutts_: interesting. override where? in Setup.hs? guess i should read the cabal manual again :) |
| 18:43:41 | <byorgey> | then look at any classes you see in its type |
| 18:43:43 | <lysgaard> | i use ghci all the time |
| 18:43:52 | <byorgey> | you can get more info about a class using :info |
| 18:43:54 | <byorgey> | like :info Integral |
| 18:43:55 | <dcoutts_> | Eelis: yes, using the hooks in Setup.hs |
| 18:44:05 | <Eelis> | dcoutts_: ok, i will look at those. thanks! |
| 18:44:09 | <byorgey> | will show you all the methods in the Integral class. |
| 18:44:17 | <Berengal> | lysgaard: or just ':info (^)' |
| 18:44:27 | <Berengal> | Prelude> :info (+) <\n> class (Eq a, Show a) => Num a where<\n> (+) :: a -> a -> a |
| 18:44:34 | <dcoutts_> | Eelis: see autoconfUserHooks in Distribution.Simple |
| 18:44:36 | <Berengal> | ↑ What I get from ghci |
| 18:44:42 | <lysgaard> | but say i want to make a (^) function for my algebra, how do i do thot then, when it's in no class? |
| 18:44:58 | <byorgey> | ah, right, at first I thought :info for (^) didn't work since it didn't show me a class... but that's because (^) isn't in a type class =) |
| 18:45:25 | <byorgey> | lysgaard: the type of (^) says it works for any arguments whose types are instances of Num and Integral |
| 18:45:40 | <byorgey> | so if your algebra type is an instance of those classes, (^) will automatically work for it |
| 18:45:47 | <Berengal> | (^) is defined in terms of the class functions. If you want it to work for your type you need to implement the class functions such that they provide the answers (^) expect of them |
| 18:47:26 | <lysgaard> | well, my algebra type includes variables, so it can't be a member of Integral or Num, but it includes the type Number, wich is an Integral. look here: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4997#a5001 |
| 18:47:48 | <vixey> | lysgaard: here's what I do |
| 18:47:52 | <vixey> | import Prelude |
| 18:48:04 | <vixey> | Number x + Number y = ... |
| 18:48:14 | <vixey> | define (+) yourself and forget about the normal definition |
| 18:50:07 | <vixey> | btw putting | at the end of all the lines except one is ugly |
| 18:50:11 | <vixey> | you can write |
| 18:50:15 | <vixey> | data X = ... |
| 18:50:21 | <vixey> | | ... |
| 18:50:22 | <vixey> | | ... |
| 18:50:23 | <vixey> | instead |
| 18:50:46 | <vixey> | also (Number a) == (Number b) = a == b can be Number a == Number b = a == b |
| 18:51:36 | <frwmanners> | lysgaard: something along the lines of (Raise a b) * (Raise c d) | a == c = Raise a (b + d) might get the standard (^) to work |
| 18:51:38 | <lysgaard> | vixey: Thanks, i love syntax tips, they always make the code cleaner |
| 18:52:45 | <frwmanners> | lysgaard: btw, is (Add (Variable "x") (Variable "y")) not equal to itself? |
| 18:55:08 | <lysgaard> | frwmanners: Well, i don't know how to express two variables, who in practise can be any number you want, in any more sensibel way |
| 18:55:49 | <frwmanners> | lysgaard: sure |
| 18:56:12 | <frwmanners> | lysgaard: but if == is really ===, then you could get away with Add a b == Add c d = a == c && b == d |
| 18:56:29 | <copumpkin> | :o |
| 18:56:32 | <frwmanners> | lysgaard: or |
| 18:56:42 | <frwmanners> | lysgaard: with the arguments flipped or something |
| 18:56:44 | <copumpkin> | ACTION is back! |
| 18:57:41 | <SubStack> | finally! |
| 18:58:12 | <dolio> | @yow! The volcano taco is back! |
| 18:58:13 | <lambdabot> | MMM-MM!! So THIS is BIO-NEBULATION! |
| 18:58:22 | <lysgaard> | frwmanners: One more time, i think you're at a wery important point, but i didn't understan how you meant i should implement it? |
| 18:59:46 | <frwmanners> | lysgaard: instance Eq Algebra where Number a == Number b = a == b; Variable a == Variable b = a == b; Add a b == Add c d = (a == c && b == d) || (a == d && b == c) |
| 19:00:10 | <frwmanners> | lysgaard: with some more cases for multiplication &c |
| 19:00:40 | <d3mn0id> | I'll come back when I know some Haskell. |
| 19:00:49 | <frwmanners> | lysgaard: assuming your algebraic expressions are finite, eventually you'll bottom out into one of those |
| 19:01:02 | <frwmanners> | lysgaard: and then a massive a == b = False at the end |
| 19:01:18 | <lysgaard> | frwmanners: They are finite, that's for shure |
| 19:01:57 | <frwmanners> | lysgaard: so right, a recursive definition of equality is probably the way to go |
| 19:02:30 | <lysgaard> | Yeah, i got your point now, genious :D |
| 19:04:43 | <lysgaard> | But to be even more general, this Eq, the one for add is also true for Multiply. And for subtraction, and division, it's true, but not the arguments flipped. Is there a way to make the algebra type so that it can figure out this? |
| 19:06:31 | <frwmanners> | lysgaard: data Algebra ... deriving Eq would be nearly there, but you'd lose the argument flipping I guess |
| 19:06:57 | <lysgaard> | frwmanners: What if i made an opperator type or something? |
| 19:07:38 | <lysgaard> | frwmanners: Or isn't that the way to go? |
| 19:07:48 | <frwmanners> | lysgaard: could work |
| 19:07:54 | <frwmanners> | lysgaard: up to you I guess |
| 19:08:32 | <frwmanners> | lysgaard: data BinOp = CommutativeOperator String | NonCommutativeOperator String would not be unsensible |
| 19:08:49 | <vixey> | I'd rather |
| 19:09:00 | <vixey> | data CommutativeOp = Add | Multiply |
| 19:09:03 | <vixey> | than 'String' |
| 19:09:13 | <frwmanners> | sure |
| 19:09:35 | <frwmanners> | depends how many exotic operators you're likely to dream up I suppose |
| 19:09:37 | <lysgaard> | Ok, what does that mean :P |
| 19:10:11 | <vixey> | anyway having == for syntactic equality, but then a different equality test for semantic equality is a good idea |
| 19:10:15 | <vixey> | so deriving Eq is cool |
| 19:10:51 | <frwmanners> | so an === operator or something? |
| 19:10:57 | <lysgaard> | Hehe, I'm doing this mostly as an exersise to get to know the typesystem of haskell. Therefore I'd like to get as complicated as i can understand |
| 19:11:24 | <frwmanners> | lysgaard: so, if you make CommutativeOp = Add | Multiply |
| 19:12:06 | <frwmanners> | lysgaard: you can then have data Algebra = Number Integer | ... | CommOp CommutativeOp Algebra Algebra |
| 19:12:36 | <frwmanners> | lysgaard: | NonCommOp NonCommutativeOp Algebra Algebra |
| 19:12:58 | <frwmanners> | where you've also got data NonCommutativeOp = Sub | Div |
| 19:13:01 | <Baughn> | ACTION finally got reactive working (work on that dependency algorithm..), and is now in the process of blowing up his head. Thanks, guys. |
| 19:13:04 | <Eelis> | dcoutts_: (fyi, reported: http://hackage.haskell.org/trac/hackage/ticket/553 ) |
| 19:13:12 | <dcoutts_> | Eelis: thanks |
| 19:14:03 | <Baughn> | Using reactive-glut to make a mini-GUI toolkit.. I can't quite understand things yet, but it looks very, very sweet. |
| 19:14:16 | <frwmanners> | lysgaard: So ``x + y'' becomes CommOp Plus (Variable "x") (Variable "y") |
| 19:14:30 | <frwmanners> | lysgaard: &c. |
| 19:14:46 | <Baughn> | Now if only I could figure out the Show instance for Event. It doesn't do what I expected (eg. let me print events as they happen). |
| 19:14:53 | <lysgaard> | frwmanners: Yeah, i think i've got it |
| 19:14:59 | <frwmanners> | lysgaard: cool |
| 19:15:05 | <hatds> | I'm making my own mini-GUI toolkit, what do you see useful about reactive? |
| 19:15:58 | <Baughn> | hatds: The sheer functionalness, basically; they've figured out a way to let me write imperative code declaratively, in a much nicer fashion than I've ever seen before |
| 19:16:11 | <roconnor> | hatds: have I told you about GuiTV before? |
| 19:16:18 | <Baughn> | hatds: ..I can't be much more specific than that, since I only just got started |
| 19:16:19 | <hatds> | roconnor: yea |
| 19:16:26 | <roconnor> | hatds: ok |
| 19:16:36 | <roconnor> | carry on then :) |
| 19:16:39 | <hatds> | roconnor: I've read a bit about it, is there something particular about that one versus the others? |
| 19:17:06 | <Baughn> | hatds: But it takes care of all the usual machinery (event handlers, callbacks, etc.) under the covers, in a way that I don't even need to know they're there |
| 19:17:07 | <roconnor> | hatds: I'm not sure. GuiTV is the only Gui system I've ever used in haskell. |
| 19:18:12 | <hatds> | my GUI system is tick-based and not event-driven, the outer system has to call app_draw and app_main |
| 19:18:23 | <hatds> | but I've been thinking about whether that could be better |
| 19:18:31 | <endojelly> | why are there bottom-up and top-down versions of everywhere (everywhere and everywhere', respectively), but only a top-down version of everywhereM in the standard library? I had to define everywhereM' myself... |
| 19:18:54 | <frwmanners> | Baughn: do you want to print Events when they happen or when they become defined? |
| 19:19:22 | <copumpkin> | omg there are |
| 19:19:23 | <pumpkin> | two of me |
| 19:19:57 | <Baughn> | frwmanners: I'm afraid I don't understand the difference. If you wouldn't mind? ;) |
| 19:20:02 | <lysgaard> | frwmanners: Think I've got it, but i'll need to add algebra to Show :S http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5005#a5005 |
| 19:20:34 | <pumpkin> | Algebra is an odd name |
| 19:21:06 | <roconnor> | newtype Algebra f a b = Algebra (f a -> b) |
| 19:21:07 | <Baughn> | frwmanners: I mean, I'd like to print them when they happen - just to make sure this is working - but I'd like to know what "defined" means in terms of reactive |
| 19:21:08 | <frwmanners> | Baughn: So, as I understand it, something like atTimes [0..] is defined from the word go, even though things only happen at times 0, 1, 2 ... |
| 19:21:17 | <pumpkin> | roconnor: that's what I normally think of |
| 19:21:20 | <lysgaard> | pumpkin: Yeah, you have any better, i don't like it either, but i'm not to good in math phrasology |
| 19:21:39 | <Baughn> | frwmanners: Makes sense |
| 19:21:45 | <pumpkin> | lysgaard: you can ask haskell to derive Show for you, too |
| 19:21:50 | <Baughn> | frwmanners: It'd just block until time reaches those.. times, I suppose |
| 19:22:03 | <frwmanners> | Baughn: ok |
| 19:22:10 | <Baughn> | frwmanners: Incidentally, what I've got right now is "sink UI{..} = pure (print 42 >> print leftButtonPressed)", which prints 42 and then 'thread blocked indefinitely' |
| 19:22:27 | <TonyTheTiger> | hiya how do i write a type signature for somthing like... twice f x = f (f x) |
| 19:22:28 | <Baughn> | frwmanners: Oh, I think I just figured it out myself.. |
| 19:22:51 | <roconnor> | twice :: (a -> a) -> a -> a |
| 19:22:52 | <Baughn> | frwmanners: pure (Behavior) describes it at time -infinity, /once/.. right? |
| 19:22:59 | <Baughn> | But mostly at time -infinity |
| 19:23:25 | <pumpkin> | TonyTheTiger: by the way, twice = join |
| 19:23:27 | <Baughn> | So of course the keys never get pressed, as far as that behavior is concerned |
| 19:23:40 | <frwmanners> | a pure Behaviour should take the same value at all time |
| 19:23:42 | <TonyTheTiger> | roconnor: but its a function that it takes, |
| 19:23:46 | <roconnor> | pumpkin: in what monad? |
| 19:23:51 | <TonyTheTiger> | roconnor: does that not matter? |
| 19:23:57 | <roconnor> | TonyTheTiger: (a -> a) is a function |
| 19:24:03 | <pumpkin> | roconnor: oh wait, that makes no sense, sorry :) |
| 19:24:09 | <frwmanners> | a pure event happens once at (-infinity) |
| 19:24:12 | <patch-tag> | hey is there a haskell package or "style" that can be used to program simple command line stuf that's okay on both unix and dows? like, really simple, just cd here and there, and then run ghc commands. hsh is really nice but seems to be unix only |
| 19:24:25 | <Baughn> | frwmanners: Right you are |
| 19:24:36 | <Baughn> | frwmanners: And my behavior is not supposed to be pure, so I shouldn't be using it. :) |
| 19:24:39 | <pumpkin> | roconnor: it could be join (.) though |
| 19:24:55 | <Baughn> | ..nice choice of function name, there |
| 19:24:56 | <pumpkin> | since it's really twice f x = ((.) f f) x |
| 19:25:04 | <TonyTheTiger> | roconnor: ohh ok, and would i need to do this too... twice :: (Num a) => (a -> a) -> a -> a? |
| 19:25:10 | <TonyTheTiger> | would that be correct? |
| 19:25:11 | <hatds> | I was almost going to do a reactive approach when I started, but I didn't know of reactive back then |
| 19:25:31 | <hatds> | the best I could come up with was like an infinite stream of inputs with unsafeInterleaveIO |
| 19:25:39 | <roconnor> | TonyTheTiger: well, you don't really need the Num constraint since the function has nothing to do with numbers, but adding the constraint doesn't really hurt much. |
| 19:26:20 | <TonyTheTiger> | roconnor: oh yeah the "function" that im calling will handle that, thanks i understand now. |
| 19:26:54 | <hatds> | having imperative push-based events does not rule out declarativeness though |
| 19:28:03 | <roconnor> | > myThreadID |
| 19:28:04 | <lambdabot> | Not in scope: `myThreadID' |
| 19:28:05 | <roconnor> | > myThreadId |
| 19:28:06 | <lambdabot> | Not in scope: `myThreadId' |
| 19:28:22 | <roconnor> | @hoogle mythreadid |
| 19:28:22 | <lambdabot> | Control.Concurrent myThreadId :: IO ThreadId |
| 19:54:00 | <Baughn> | conal: Would you accept a reactive-glut patch to add leftButton/rightButton Behavior Bools and equivalent keyboard behavior? (I'm very new to this whole "reactive" thing, but.. kinda need those) |
| 19:54:25 | <lysgaard> | I've gotten a bit furter, but now i have some problems with a simplyfy function. I think i've missunderstood the typesystem or something :S http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5005#a5006 |
| 19:54:39 | <TonyTheTiger> | hi guys can explain to me how you use null and where it would be appropriate? |
| 19:55:53 | <lysgaard> | TonyTheTiger: What do you want to do? |
| 19:56:17 | <Berengal> | TonyTheTiger: We don't have null, only nil and Nothing |
| 19:56:21 | <lysgaard> | TonyTheTiger: Null like in imperative languages (c, python ...) does not exist |
| 19:56:22 | <pejo> | TonyTheTiger, whenever you want to know if a list is empty or not. |
| 19:56:49 | <lysgaard> | TonyTheTiger: All functions in haskell has to return someting |
| 19:56:55 | <adamvo> | > null [] |
| 19:56:56 | <lambdabot> | True |
| 19:57:09 | <lysgaard> | What you need is I guess is Maybe |
| 19:57:24 | <Baughn> | conal: ..make that Set Key for the keyboard |
| 19:57:31 | <pejo> | TonyTheTiger, (but pattern matching might be more clear in a recursive function, for example). |
| 19:58:10 | <vixey> | > null null |
| 19:58:12 | <lambdabot> | Couldn't match expected type `[a]' |
| 19:58:25 | <vixey> | null is pretty much useless |
| 19:58:33 | <vixey> | I guess there are sometimes you can use it |
| 19:58:46 | <Berengal> | vixey: I use if null foo then ... often enough |
| 19:58:57 | <roconnor> | @type let foo 7 = () in foo |
| 19:58:58 | <lambdabot> | forall t. (Num t) => t -> () |
| 19:59:05 | <vixey> | lysgaard: You need to write: |
| 19:59:07 | <pumpkin> | > null [null] |
| 19:59:08 | <lambdabot> | False |
| 19:59:12 | <FunctorSalad> | hehe |
| 19:59:12 | <vixey> | CommOpp (Add a b) = ... |
| 19:59:14 | <pumpkin> | > null [null [null]] |
| 19:59:14 | <vixey> | it can't be |
| 19:59:15 | <lambdabot> | False |
| 19:59:17 | <vixey> | CommOpp Add a b = ... |
| 19:59:23 | <pumpkin> | > null [null [null [null]]] |
| 19:59:25 | <lambdabot> | False |
| 19:59:25 | <vixey> | the reason is because 'CommOpp' isn't an operator |
| 19:59:33 | <FunctorSalad> | > fix (\x -> null [x]) |
| 19:59:35 | <lambdabot> | False |
| 19:59:37 | <FunctorSalad> | :o |
| 19:59:37 | <ziman> | > fix (nul . (:[])) |
| 19:59:38 | <lambdabot> | Not in scope: `nul' |
| 19:59:44 | <TonyTheTiger> | guys can you explain to me how null works and applying it? |
| 19:59:44 | <ziman> | > fix (null . (:[])) |
| 19:59:46 | <lambdabot> | False |
| 19:59:47 | <FunctorSalad> | ziman :) |
| 19:59:54 | <ziman> | FunctorSalad, you got it right ;) |
| 20:00:00 | <Berengal> | @type null |
| 20:00:02 | <lambdabot> | forall a. [a] -> Bool |
| 20:00:12 | <lysgaard> | vixey: CommOpp is an constructor? |
| 20:00:22 | <adamvo> | @src null |
| 20:00:22 | <lambdabot> | null [] = True |
| 20:00:22 | <lambdabot> | null (_:_) = False |
| 20:00:29 | <vixey> | fus |
| 20:00:32 | <vixey> | yes* |
| 20:00:36 | <Berengal> | map null $ iterate (():) [] |
| 20:00:53 | <Berengal> | > map null $ iterate (():) [] |
| 20:00:55 | <lambdabot> | [True,False,False,False,False,False,False,False,False,False,False,False,Fal... |
| 20:00:57 | <TonyTheTiger> | huh, its alot more simple than i thought about |
| 20:01:00 | <TonyTheTiger> | cheers |
| 20:01:46 | <lysgaard> | vixey: Yay! I think i'm getting the hang of this |
| 20:01:53 | <vixey> | :) |
| 20:02:14 | <lysgaard> | vixey: But how can i do the patternmatching then? |
| 20:02:15 | <FunctorSalad> | ISTR there's a rewrite rule that replaces stuff like (x==[]) with a pattern match |
| 20:02:24 | <vixey> | lysgaard pattern matching of what? |
| 20:02:28 | <FunctorSalad> | or a different ghc optimization |
| 20:02:40 | <copumpkin> | people talk about all haskell data being codata |
| 20:02:44 | <lysgaard> | vixey: Eg: | a == - b = Number 0 for Add |
| 20:02:45 | <copumpkin> | or am I misremembering? |
| 20:02:48 | <adamvo> | @type (==[]) |
| 20:02:50 | <lambdabot> | forall a. (Eq a) => [a] -> Bool |
| 20:03:03 | <FunctorSalad> | copumpkin: :O I considered asking this several minutes ago. |
| 20:03:04 | <vixey> | adamvo: yeah null has to be pattern matching |
| 20:03:15 | <osfameron> | copumpkin: coremembering? |
| 20:03:36 | <FunctorSalad> | copumpkin: I wonder what the full story behind this "ADTs are both initial algebras and final coalgebras" thing is |
| 20:03:39 | <FunctorSalad> | :) |
| 20:03:54 | <sjanssen> | FunctorSalad: I don't think there is a rewrite rule for that, it is invalid |
| 20:04:09 | <copumpkin> | FunctorSalad: hah :P I got tired of wondering what coinduction was so I looked it up, and it mentioned that codata was coninductively defined data, and was typically infinite... then I remembered someone saying that all haskell data was codata so now I'm confused :P |
| 20:04:33 | <FunctorSalad> | sjanssen: not a rewrite rule I guess, but I remember seeing compiler output like "replacing (==) with pattern match"? |
| 20:04:43 | <conal> | Baughn: i like the Bool & Set suggestions. perhaps both could implemented on top of current interface plus button release events. |
| 20:04:45 | <roconnor> | copumpkin: I think I said all data in Haskell is codata |
| 20:04:51 | <copumpkin> | aha :) |
| 20:04:54 | <roconnor> | copumpkin: but It's not entirely true I guess |
| 20:04:57 | <copumpkin> | could you elaborate on that? I'm clueless |
| 20:04:58 | <copumpkin> | oh |
| 20:05:06 | <dolio> | In a complete partial order category, which is where Haskell gets its semantics, all initial algebras are final coalgebras and vice versa. |
| 20:05:08 | <Peaker> | Baughn: I wrote a Set Key thing myself for Reactive |
| 20:05:11 | <roconnor> | cause data Foo = Foo (Foo -> Bool) can be done in haskell |
| 20:05:18 | <roconnor> | and who know WTF that is. |
| 20:05:41 | <roconnor> | maybe dolio knows what it is. |
| 20:06:14 | <dolio> | I've never been able to find a category theoretic proof of it, but the fact that you can define both fold and unfold for every suitable datatype using general recursion pretty much demonstrates it. |
| 20:06:38 | <Peaker> | Baughn: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5007#a5007 |
| 20:06:40 | <dolio> | Considering only strictly positive types, and not the weird ones like roconnor just mentioned. |
| 20:06:44 | <vixey> | dolio: can't it always be done by single step structural recursion? |
| 20:06:56 | <copumpkin> | hmm |
| 20:07:01 | <Baughn> | conal: That's fine. I need button release events to implement them anyway, so might as well export them |
| 20:07:07 | <Baughn> | conal: I'll get you a patch soonish, then |
| 20:07:07 | <copumpkin> | what would codolio say though? |
| 20:07:34 | <Peaker> | conal: ah, you're here, here's a Behavior (Set Key) implementation on top of existing keyAction: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5007#a5007 |
| 20:08:11 | <Baughn> | conal, Peaker: Thanks, I'll just include that one then. :) |
| 20:08:15 | <FunctorSalad> | dolio: the thing I find slightly confusing is that "infinite lists over A" is not an initial \X -> X * (A -> X -> X) algebra in Set |
| 20:08:54 | <Peaker> | Baughn: note that Behavior loses the discrete nature of the events, though. Maybe its better to use accumE and get an event, instead |
| 20:09:10 | <mreh> | how can i determine what GHC a certain library was distributed with? |
| 20:09:31 | <FunctorSalad> | err wait that functor is wrong |
| 20:09:37 | <Baughn> | Peaker: We're getting leftButtonReleased too, as per conal's request |
| 20:09:45 | <dolio> | F X = A * X you mean? |
| 20:09:49 | <FunctorSalad> | \X -> 1 + A*X |
| 20:09:58 | <dolio> | Oh. |
| 20:10:00 | <Baughn> | Peaker: So you can use eitherE |
| 20:11:11 | <FunctorSalad> | I guess thinking about it in terms of sets is totally misleading |
| 20:11:29 | <vixey> | yeah down with sets!! |
| 20:12:02 | <mmorrow> | ACTION gets his pitchfork and riot shoes on |
| 20:12:38 | <dolio> | Well, to be honest, I'm not too familiar with that area of discussion, either. I'd have to think about it a bit. |
| 20:13:09 | <roconnor> | start with Cale! he is a set sympathizer! |
| 20:13:14 | <FunctorSalad> | =) |
| 20:13:18 | <dolio> | However, the initial algebra in Set would have to be such that for any other algebra, there's a total function to it from the initial algebra. |
| 20:13:36 | <FunctorSalad> | dolio: yep, in Set the intial algebra is just the finite lists |
| 20:14:07 | <FunctorSalad> | the infinite risks aren't "reached" by specifying an algebra |
| 20:14:16 | <FunctorSalad> | so they could map to anything, hence no unique morphism |
| 20:14:26 | <FunctorSalad> | *infinite lists |
| 20:14:28 | <dolio> | And there's probably not always a total function from the set of possibly infinite lists to other appropraite sets, so that's why it isn't initial. |
| 20:15:06 | <dolio> | Like, for instance, foldr (+) 0 :: [Natural] -> Natural. |
| 20:15:13 | <roconnor> | I wish I knew what the semantics for data types in haskell were. |
| 20:15:43 | <roconnor> | @type foldr (+) 0 :: [Natural] -> Natural. |
| 20:15:44 | <lambdabot> | parse error on input `.' |
| 20:15:47 | <FunctorSalad> | dolio: there exist plenty of total functions, but you have to arbitrarily choose the image of infinite lists |
| 20:15:47 | <roconnor> | @type foldr (+) 0 :: [Natural] -> Natural |
| 20:15:48 | <lambdabot> | [Natural] -> Natural |
| 20:16:04 | <roconnor> | dolio: Haskell's Natural contains infinity |
| 20:16:09 | <roconnor> | @type infinity |
| 20:16:11 | <lambdabot> | Natural |
| 20:16:16 | <Beelsebob> | wow, Haskell is green today |
| 20:16:27 | <FunctorSalad> | (or rather, you get to make a choice for every equivalence class of infinite lists, where two lists are equivalent if they have the same tail eventually) |
| 20:16:29 | <dolio> | FunctorSalad: Well, yes, but they have to satisfy certain laws to qualify as algebra homomorphisms. |
| 20:17:14 | <dolio> | roconnor: Yes, but we're talking about Set, not Hask. |
| 20:17:19 | <TonyTheTiger> | is this stuff true about haskell? |
| 20:17:20 | <TonyTheTiger> | http://uncyclopedia.wikia.com/wiki/Haskell |
| 20:17:43 | <pumpkin> | lol |
| 20:17:50 | <roconnor> | dolio: didn't you see the pitchforks? |
| 20:17:54 | <FunctorSalad> | dolio: hmm right, if the algebra we map to has operations nil and cons, then we need f [] = nil and f (x:xs) = cons x (f xs) |
| 20:18:08 | <pumpkin> | TonyTheTiger: "Uncyclopedia, the content-free encyclopedia" |
| 20:18:12 | <FunctorSalad> | dolio: so I think you're right that morphisms may not exist (not sure) |
| 20:18:18 | <nagnatron> | lmao |
| 20:18:29 | <dolio> | roconnor: We're throwing out Set? Then I guess we won't giving semantics to our total languages. :) |
| 20:18:50 | <pumpkin> | > fix$(<$>)<$>(:)<*>((<$>((:[{- OH MY GOD IT'S A COMMENT!!! -}])<$>))(=<<)<$>(*)<$>(*2))$1 |
| 20:18:53 | <lambdabot> | [1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,... |
| 20:18:56 | <pumpkin> | lol |
| 20:18:58 | <roconnor> | dolio: not using Set we won't. |
| 20:19:19 | <SamB> | dolio: Total langauges don't use *that* Set |
| 20:19:41 | <TonyTheTiger> | pumpkin: funny. :) |
| 20:19:45 | <roconnor> | dolio: we use type theory for our semantics. |
| 20:19:50 | <dolio> | What Set do they use, other than the category of sets and total functions? |
| 20:19:56 | <roconnor> | dolio: which is great because we are defining type theory. |
| 20:20:02 | <roconnor> | dolio: makes it much easier. |
| 20:20:05 | <[bjoern]> | I had trouble coming up with the right signature for this function (or have some other problem i have yet to debug...) |
| 20:20:06 | <[bjoern]> | basically i want f(List of triples of X, list of X, list of triples of X) maps to a list of triples of X (X in this case is Int) |
| 20:20:07 | <SamB> | dolio: they don't use sets from set theory! |
| 20:20:22 | <dolio> | That doesn't answer my question. |
| 20:20:36 | <[bjoern]> | I get "Occurs check: cannot construct the infinite type: x = [x]" |
| 20:20:51 | <FunctorSalad> | dolio: you're right, "foldr (+) []" with domain the infinite lists doesn't exist in Set. if x = cycle [1], then we have 1:x == x, but there's no natural fx such that 1+fx==fx |
| 20:20:54 | <SamB> | they use more constructive things |
| 20:20:58 | <roconnor> | [(x,x,x)] -> [x] -> [(x,x,x)] -> [(x,x,x)] |
| 20:21:07 | <[bjoern]> | ACTION tries |
| 20:21:26 | <sjanssen> | [bjoern]: the error probably means there is an error with your code, not the signature |
| 20:21:40 | <FunctorSalad> | btw guys I really didn't mean to start a Set vs. Type Theory war ;) |
| 20:21:41 | <pumpkin> | that's an odd signature |
| 20:21:41 | <pumpkin> | what does it do? |
| 20:21:42 | <[bjoern]> | Yeah, ideas how to debug that? |
| 20:21:55 | <roconnor> | [bjoern]: I'm assuming that you rewrite your function in the usual curried style. |
| 20:22:00 | <dolio> | FunctorSalad: Right. So I think that shows that the initial algebra of 1 + A*X in Set doesn't have infinite lists. |
| 20:22:14 | <mreh> | are they going to bundle cabal with GHC soon? |
| 20:22:22 | <roconnor> | ACTION bets [bjoern] is dealing with colour. |
| 20:22:29 | <pumpkin> | mreh: nope, cabal-install comes with the platform though |
| 20:22:36 | <dolio> | SamB: What category would you use if you want to talk about the initial algebra semantics of a total functional programming language? |
| 20:22:39 | <FunctorSalad> | *"foldr (+) 0" actually |
| 20:22:39 | <dcoutts_> | mreh: that's what the platform does |
| 20:22:41 | <[bjoern]> | no, the triples are weighted edges in a graph |
| 20:22:42 | <pumpkin> | mreh: the cabal infrastructure already comes with ghc |
| 20:22:46 | <roconnor> | damn |
| 20:22:46 | <Berengal> | System.IO.Unsafe.Really.IMeanIt.reallyReallyAbsurdlyUnsafePerformIOShameOnYou |
| 20:22:47 | <vixey> | FunctorSalad: was there a war and I missed it? |
| 20:22:54 | <SamB> | dolio: dunno! |
| 20:22:55 | <mreh> | pumpkin: but i still need the other three packages |
| 20:23:02 | <dolio> | The one I've typically seen is Set. |
| 20:23:05 | <roconnor> | [bjoern]: you should paste your code |
| 20:23:07 | <roconnor> | @paste |
| 20:23:07 | <lambdabot> | Haskell pastebin: http://hpaste.org/new |
| 20:23:10 | <SamB> | I didn't haven't even failed category theory yet! |
| 20:23:10 | <mreh> | i'm trying to build cabal myself |
| 20:23:31 | <lysgaard> | vixey: If you look at the bottom of the hpaste, "instance Calculate" you see that i try to find special cases for the expressions eg: a * 1 = a. How do i make that part work |
| 20:23:32 | <SamB> | I have yet to discover where I might be able to attempt this feat |
| 20:23:34 | <pumpkin> | mreh: the bootstrap script doesn't work? |
| 20:23:35 | <dcoutts_> | mreh: you can use the bootstrap script to automate that |
| 20:23:43 | <mreh> | okay |
| 20:23:54 | <dcoutts_> | @quote stereo |
| 20:23:55 | <lambdabot> | LoganCapaldo says: * LoganCapaldo must resist urge to mention stereo |
| 20:23:58 | <dcoutts_> | bah |
| 20:24:04 | <vixey> | lysgaard: to write something like this I would use a fold |
| 20:24:04 | <FunctorSalad> | vixey: seemed like it was about to start, people already had their riot shoes out |
| 20:24:16 | <SamB> | dcoutts: ooh, I like it! |
| 20:24:17 | <SamB> | variety |
| 20:24:20 | <mreh> | pumpkin, dcoutts_: i have 6.8.3, and i've been told that i have to do it manually |
| 20:24:29 | <hydo> | Does the gitit author happen to hang out here by chance? I thought I'd ask before I sent him email. |
| 20:24:44 | <SamB> | hydo: would that be gwern? |
| 20:24:47 | <dcoutts_> | mreh: the bootstrap script will work fine with 6.8.x |
| 20:24:49 | <mreh> | atleast that's what RHW says |
| 20:24:51 | <Heffalump> | SamB: no |
| 20:24:57 | <mreh> | RWH |
| 20:25:01 | <mmorrow> | the gitit guy is a philosophy professor :) |
| 20:25:06 | <hydo> | SamB: jmacfarlane |
| 20:25:09 | <SamB> | oh. |
| 20:25:10 | <lysgaard> | Would you mind explaining please? |
| 20:25:10 | <FunctorSalad> | SamB: of course Set would be unnecessarily large because countable sets should suffice for the semantics of a programming language? |
| 20:25:16 | <hydo> | ah, so probably doesn't hang out on irc. hehe |
| 20:25:20 | <dcoutts_> | mreh: right, RWH was published before the bootstrap script |
| 20:25:20 | <SamB> | does gwern at least hack on gitit a lot ? |
| 20:25:22 | <FunctorSalad> | but I don't see why you couldn't use it |
| 20:25:32 | <Heffalump> | SamB: yes, or at least on filestore which is closely related |
| 20:25:32 | <SamB> | hydo: uh, but that sounded like an IRC nick to me! |
| 20:25:52 | <hydo> | SamB: I was abbreviating his name... for reasons still unkown to me. |
| 20:25:56 | <SamB> | so ... since when do philosophy professors know how to program ? |
| 20:26:09 | <lysgaard> | vixey: You mean like folding over the expression? |
| 20:26:10 | <ent20py1> | since prolog :P |
| 20:26:14 | <SamB> | much less in Haskell! |
| 20:26:26 | <Eelis> | is there a way to get cabal to copy a directory in whole when installing? i tried putting "data-files: thedir" in my .cabal, but this produces "Setup.hs: thedir: copyFile: inappropriate type (is a directory)" |
| 20:26:59 | <FunctorSalad> | roconnor: are you saying that the problem with "data Foo = Foo (Foo -> Bool)" is that the functor is contravariant? hmm |
| 20:27:07 | <Baughn> | conal: Probably a reactive issue; it occurs to me that flipFlop should not generate a new (internal) event when it does not, in fact, flop |
| 20:27:22 | <dcoutts_> | Eelis: you can use a limited form of wildcard in Cabal 1.6 and later |
| 20:27:34 | <Eelis> | dcoutts_: yes, i noticed, but that would actually be very painful for my case |
| 20:27:47 | <dcoutts_> | Eelis: but there's deliberately no recursive directory copy |
| 20:27:54 | <Eelis> | dcoutts_: what's the rationale? |
| 20:27:58 | <Eelis> | annoying people? |
| 20:28:08 | <dcoutts_> | Eelis: accidentally picking up too many files |
| 20:28:11 | <Baughn> | conal: Anyway. Patch: http://brage.info/~svein/reactive-glut.patch |
| 20:28:12 | <Heffalump> | debris |
| 20:28:27 | <Eelis> | dcoutts_: sigh. |
| 20:28:35 | <conal> | Baughn: "internal" event? |
| 20:28:57 | <[bjoern]> | Okay, figured it out. needed to replace a 'a:b' by '(a:b)' |
| 20:29:01 | <Baughn> | conal: Whatever causes the action to be re-executed (well, "change") in action <$> behaviour |
| 20:29:06 | <Eelis> | dcoutts_: i guess i'll have to override some more hooks then. but seriously, this is plain stupid |
| 20:29:16 | <roconnor> | [bjoern]: a common error |
| 20:29:34 | <dcoutts_> | Eelis: if you can think of a better balance in expressiveness vs safety then do say so |
| 20:29:59 | <Baughn> | conal: You'll see what I mean if you try adaptSimple "" (print <$> keyboard) |
| 20:30:04 | <Peaker> | Baughn: wouldn't it be nicer to define those events in terms of the GLUT events, rather than have many events created with legacy adapters? |
| 20:30:09 | <Eelis> | dcoutts_: well, personally i think the current solution is completely unbalanced. it should just copy the directory. making life miserable for people who actually have a need for the functionality, just to protect those that don't, is silly |
| 20:30:15 | <FunctorSalad> | roconnor: how about F: Endo(Hask * Hask^op), F(X,Y) = (Y -> Bool, X -> Bool)? but that's absolutely ad-hoc ;) |
| 20:30:39 | <lukeo05> | [bjoern]: i have done that a ridiculous amount of times, and still keep doing it. the error message is always never helpful to realize the stupid error. |
| 20:31:06 | <Peaker> | > (maxBound :: Int) + 1 |
| 20:31:10 | <lambdabot> | -9223372036854775808 |
| 20:31:16 | <Peaker> | yairchu: here's an overflow |
| 20:31:16 | <dcoutts_> | Eelis: suppose we added "data-files: dir/" should it include hidden files etc too? |
| 20:31:29 | <conal> | Baughn: maybe you mean that stepper isn't optimized for event occurrences that switch from a value to the same value. |
| 20:31:38 | <mreh> | so am i bootstrapping cabal, or cabal-install? |
| 20:31:38 | <Baughn> | Peaker: Probably, yes. Might be nice to have the callbacks stuff their events directly into an FRP Event |
| 20:31:38 | <Eelis> | dcoutts_: yes, the whole thing. i like the idea with the trailing / ! |
| 20:31:59 | <Baughn> | conal: I might. I didn't check to see how flipFlop is implemented. ;) |
| 20:32:22 | <Peaker> | > 600851475143::Int |
| 20:32:23 | <lambdabot> | 600851475143 |
| 20:32:52 | <dcoutts_> | Eelis: and we'd have to check for symlinks (and not follow them, or at least check for no cycles) etc etc |
| 20:33:01 | <Peaker> | > showHex 600851475143 "" |
| 20:33:03 | <lambdabot> | "8be589eac7" |
| 20:33:06 | <conal> | Baughn: FRP isn't really meant to be used with IO (e.g., print). i regrettably took a short-cut and exposed and IO interface, but i really mean something more like O. |
| 20:33:26 | <dcoutts_> | Eelis: which is the other problem, safe recursive dir traversal is not trivial or portable |
| 20:33:28 | <Eelis> | dcoutts_: yes, some work would be involved. i never said it would be free |
| 20:33:35 | <conal> | Baughn: in other words, it's my inteface-bad that allows you to notice the missing optimization. |
| 20:33:41 | <dcoutts_> | Eelis: feel free to file a feature request :-) |
| 20:33:44 | <Heffalump> | conal: wouldn't print be O? |
| 20:33:48 | <Eelis> | dcoutts_: alright, i will |
| 20:33:48 | <conal> | i'll remove the IO stuff at some point. |
| 20:34:08 | <Baughn> | conal: How's that going to work? Wrapping every function in the opengl library? -_- |
| 20:34:33 | <conal> | Heffalump: not in the sense i mean. more like idempotent actions. though that's probably not quite it either. |
| 20:34:49 | <Baughn> | Besides, I might genuinely want to do IO when a user presses some button in my ui |
| 20:34:50 | <Peaker> | a "denotational debugger" for Haskell could be useful, an "operational debugger" could be difficult (hard to debug lazy code as execution jumps all over the place), but if you just debug the values, and not how they're computed, its easy and useful |
| 20:34:56 | <conal> | an example is updating a visual display, such as a gui widget. |
| 20:35:02 | <skorpan> | what does this mean in a type signature? (Tok Token ~ Element syntax) => .. |
| 20:35:12 | <Heffalump> | conal: so O within the scope of the reactive thing |
| 20:35:22 | <conal> | Baughn: a semantic mis-fit for behaviors, then. |
| 20:35:22 | <Heffalump> | skorpan: type equality |
| 20:35:26 | <Heffalump> | it's a new type families thing |
| 20:35:43 | <skorpan> | Heffalump: so it means kind of like Tok Token = Element? |
| 20:35:48 | <Heffalump> | yes |
| 20:35:52 | <Baughn> | conal: Well, of course I'll make my IO idempotent too |
| 20:36:04 | <Heffalump> | well, Tok Token = Element syntax in the case you quoted |
| 20:36:09 | <mreh> | oh, can't I bootstrap on Windows? |
| 20:36:18 | <Heffalump> | one of Tok or Element would have to be a type function for it to be satisfiable |
| 20:36:24 | <Baughn> | conal: But.. right, I see what you mean. I did mention I'm not experienced with FRP. :) |
| 20:36:26 | <conal> | Baughn: oh. what'll your idempotent IO be like? |
| 20:36:35 | <Baughn> | conal: Reading files? |
| 20:38:21 | <conal> | Baughn: oh, hm. i guess you'd have to figure out how you want to relate file-reading to the *semantic* framework of FRP. For instance, files as (immutable) behaviors or events. |
| 20:38:35 | <conal> | Baughn: that's what i'd do. |
| 20:38:55 | <Baughn> | conal: I'm still trying to work out how to actually do opengl output. :/ |
| 20:39:31 | <Baughn> | I certainly don't want to re-render a frame every time the user does any input whatsoever |
| 20:39:49 | <dolio> | FunctorSalad: I've read my fair share of papers on categorical sem |