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:43 | <Jedai> | Nehal: ... it seems to me that to detect duplicates it is far better to use a canonical form |
| 00:00:59 | <aavogt> | > (4%6) == (2%3) |
| 00:01:00 | <lambdabot> | True |
| 00:01:13 | <Jedai> | Nehal: In other words the behaviour of Ratio seems much better for this assignment than the one you asked for |
| 00:01:33 | <Nehal> | yes i think i know what you are saying |
| 00:02:38 | <Jedai> | I'm not sure to understand the assignment, isn't it really easy ? |
| 00:03:18 | <Nehal> | Jedai: this is a basic haskell course and this is the first assignment.... i wouldn't be surprised if it seems very easy for you :) |
| 00:04:25 | <Base> | umm how can i do [1..5] -> [1,[2,[3,[4,[5]]]]] |
| 00:04:49 | <Ralith> | \(x:xs) -> x:[xs] |
| 00:05:17 | <Jedai> | Nehal: If I understood the assignment correctly I would suggest that you forget this idea of "detecting duplicates", it is far easier to produce this infinite list directly |
| 00:05:21 | <Cale> | It seems easier to generate the list in such a way that there are no duplicates from the outset than to remove them after the fact. |
| 00:05:42 | <Jedai> | Base: You can't |
| 00:05:43 | <Nehal> | Jedai: yeah, i was thinking about it the wrong way |
| 00:05:51 | <Cale> | Base: That list, what type does it have? |
| 00:06:05 | <Base> | Int |
| 00:06:19 | <Cale> | Base: Int is not a list type |
| 00:06:34 | <Base> | ummm can i do it (1,(2,(3 ... ? |
| 00:06:40 | <Jedai> | Base: the basic list type in Haskell is homogenous, that is every element of it has the type, that is not the case of [1,[2,[3,[4,[5]]]]] |
| 00:07:03 | <Jedai> | Base: That you can |
| 00:07:07 | <Cale> | Do you perhaps mean 1 : (2 : (3 : (4 : (5 : [])))) ? |
| 00:07:16 | <Cale> | Because [1..5] is already equal to that. |
| 00:07:20 | <Jedai> | Base: But I don't see why that would interest you ? |
| 00:07:37 | <Base> | It's part of a huge set of questions |
| 00:07:51 | <Base> | nothing specific |
| 00:08:08 | <Cale> | > (1, (2, (3, (4, (5, ()))))) |
| 00:08:09 | <lambdabot> | (1,(2,(3,(4,(5,()))))) |
| 00:08:16 | <Cale> | :t (1, (2, (3, (4, (5, ()))))) |
| 00:08:17 | <Jedai> | Base: if they're course question, I'm pretty sure you don't need (1,(2,(3,4))) |
| 00:08:17 | <lambdabot> | forall t t1 t2 t3 t4. (Num t4, Num t3, Num t2, Num t1, Num t) => (t, (t1, (t2, (t3, (t4, ()))))) |
| 00:08:47 | <Cale> | ^^ this is a type which you're very unlikely to actually want, basically |
| 00:09:07 | <Jedai> | Base: I would suggest that trying to use this type is an error itself, you're unlikely to need or want it |
| 00:10:13 | <cads> | hey, what's a representation of a module that I can use to understand what is meant when people say ML has a first class module system? |
| 00:12:09 | <cads> | I was thinking of a lambda function that takes a few parameters representing the functional parameters that a module is dependent on, and returns an associative map of name/function pairs, where the functions are derived in part from the parameters given |
| 00:13:25 | <Cale> | cads: Well, suppose that we treated the export lists of modules more like the types of values. A module could express that it was parametrised over any module which had a given signature. |
| 00:14:14 | <cads> | ah, I see |
| 00:15:03 | <Cale> | cads: A good example of this might be something like all the various libraries for working with HTML, and the various different String and ByteString libraries. An XML/HTML parsing library could say "you can apply me to the string library you'd like to use, and I will parse strings of that type" |
| 00:15:51 | <Cale> | So the effect is not unlike that of typeclasses, but the way in which things are expressed is somewhat different. |
| 00:16:43 | <cads> | if we neglect to express it in an algebraic type symbolism, can we realize the above with my module-lambda idea when our module-lambda can receive as a parameter another module lambda, or the associative map produced by instantiating one? |
| 00:17:23 | <Cale> | I think your idea basically sounds like it. |
| 00:18:00 | <aavogt> | it there a fundamental reason that ghc needs hs-boot files to compile mutually recursive modules? |
| 00:18:14 | <Cale> | aavogt: Not a particularly fundamental one. |
| 00:18:49 | <Cale> | aavogt: But the annoyance of it is enough that I usually try to avoid cyclic module dependencies altogether. |
| 00:19:10 | <Cale> | aavogt: Usually it's sufficient to move datatypes into a separate module. |
| 00:19:56 | <centrinia> | Consolidation also helps. |
| 00:20:27 | <aavogt> | Cale: true. So it hasn't been solved because it isn't annoying enough, not because it is that difficult |
| 00:21:11 | <Cale> | aavogt: Well, I think it's been designed with a focus on separate compilation. It doesn't really (as far as I know) have a facility for compiling a bunch of modules together as one. |
| 00:22:01 | <Cale> | It would need to do that, on strongly connected components of the module dependency graph, if it was going to resolve the cyclic dependencies on its own. |
| 00:22:02 | <aavogt> | I see |
| 00:23:39 | <Cale> | and yeah, while sometimes it can be annoying, it's usually not *too* hard to jostle things around a bit to remove cyclic dependencies. |
| 00:27:02 | <QtPlaty[HireMe]> | Has anyone else had problems hitting research.microsoft.com ? |
| 00:27:29 | <dolio> | It's pretty flakey. |
| 00:50:13 | <Baughn> | ACTION uses fmap.fmap.fmap in anger for the first time |
| 00:52:09 | <Smorg> | Aww, length [0..] doesn't say infinity, it just maxes the cpu. Lame. |
| 00:52:48 | <Smorg> | and only one core! I demand multi-threaded counting to infinity. |
| 00:52:52 | <dolio> | > (5 :: Natural) < genericLength [0..] |
| 00:52:53 | <lambdabot> | True |
| 00:53:32 | <Smorg> | hm interesting. |
| 00:53:34 | <centrinia> | Weird. |
| 00:54:01 | <centrinia> | > (5 :: Natural) - (6 :: Natural) |
| 00:54:02 | <lambdabot> | * Exception: Natural: (-) |
| 00:54:21 | <Jedai> | > (5 :: Natural) - 3 |
| 00:54:22 | <lambdabot> | 2 |
| 00:54:26 | <zbanks> | With ghc (at least), is it possible to cross compile an executable wo/ having ghc ported to the platform? |
| 00:54:49 | <aavogt> | > (5 :: Natural) > (iterate succ undefined !! 6) |
| 00:54:50 | <lambdabot> | * Exception: Prelude.undefined |
| 00:55:24 | <zbanks> | For example, could I compile a program for ARM just using the arm toolchain and not porting ghc? |
| 00:56:02 | <aavogt> | > succ undefined :: Natural |
| 00:56:04 | <lambdabot> | * Exception: Prelude.undefined |
| 00:56:33 | <aavogt> | > (5 :: Natural) > (iterate (1+) undefined !! 6) |
| 00:56:34 | <lambdabot> | False |
| 00:56:46 | <Cale> | I think that subtraction on naturals should be extended with 0 in the case that the second is larger than the first. |
| 00:56:57 | <aavogt> | why is Enum for naturals so strict? |
| 00:57:18 | <dolio> | Probably goes through Int. |
| 00:57:21 | <Cale> | (because that's how lists behave) |
| 00:57:40 | <aavogt> | @src Enum Natural |
| 00:57:41 | <lambdabot> | Source not found. Do you think like you type? |
| 00:57:52 | <Cale> | Natural is from the numbers package on hackage. |
| 00:58:09 | <dolio> | > maxBound :: Int |
| 00:58:11 | <lambdabot> | 9223372036854775807 |
| 00:58:26 | <dolio> | > succ (9223372036854775807 :: Natural) |
| 00:58:29 | <lambdabot> | * Exception: stack overflow |
| 00:58:36 | <dolio> | Heh. |
| 00:59:35 | <aavogt> | Cale: hmm, in that package: succ = (+1) |
| 01:00:06 | <dolio> | Oh, that's bad. |
| 01:00:13 | <dolio> | Should be (1+). |
| 01:00:15 | <roconnor> | aavogt who says Enum for the Naturals is strict? |
| 01:00:41 | <Cale> | Uh, that library doesn't define succ at all. |
| 01:00:56 | <roconnor> | > [0..] :: [Natural] |
| 01:00:56 | <Cale> | http://hackage.haskell.org/cgi-bin/hackage-scripts/package/numbers |
| 01:00:57 | <lambdabot> | [0,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,... |
| 01:01:03 | <aavogt> | http://hackage.haskell.org/packages/archive/numbers/2009.5.18.1/doc/html/src/Data-Number-Natural.html#Natural |
| 01:01:30 | <Cale> | ah, yes |
| 01:01:52 | <aavogt> | > 1 > succ (succ undefined) -- roconnor, says this! |
| 01:01:54 | <lambdabot> | * Exception: Prelude.undefined |
| 01:02:11 | <roconnor> | dah |
| 01:02:13 | <Cale> | Ah, it's (+1) and not (1+) |
| 01:02:17 | <aavogt> | > 1 > 2+undefined -- should be like this |
| 01:02:18 | <lambdabot> | * Exception: Prelude.undefined |
| 01:02:22 | <Cale> | That's foolish :) |
| 01:02:45 | <roconnor> | @tell lilac you screwed up your Enum Natural instance. succ needs to be (1+) not (+1). |
| 01:02:45 | <lambdabot> | Consider it noted. |
| 01:02:56 | <aavogt> | > 1 > 1+(1+undefined) |
| 01:02:58 | <lambdabot> | * Exception: Prelude.undefined |
| 01:03:17 | <dolio> | I thought augustss did numbers. |
| 01:03:21 | <roconnor> | > 1 < 1+(1+undefined) |
| 01:03:21 | <aavogt> | > (1:Natural) > succ (succ undefined) -- roconnor, says this! |
| 01:03:22 | <lambdabot> | Not in scope: data constructor `Natural' |
| 01:03:22 | <lambdabot> | * Exception: Prelude.undefined |
| 01:03:29 | <Cale> | sigh... |
| 01:03:29 | <aavogt> | > (1::Natural) > succ (succ undefined) -- roconnor, says this! |
| 01:03:31 | <lambdabot> | * Exception: Prelude.undefined |
| 01:03:43 | <roconnor> | > 1 > 1+(1+(undefined::Natural)) |
| 01:03:45 | <lambdabot> | False |
| 01:03:45 | <aavogt> | > (1::Natural) > (2+ undefined) |
| 01:03:46 | <lambdabot> | False |
| 01:03:48 | <Base> | okay I'm out |
| 01:03:54 | <Cale> | There's an excellent natural number library which is smarter about representation anyway... http://hackage.haskell.org/cgi-bin/hackage-scripts/package/nat |
| 01:03:59 | <Base> | lambdabot thanks a lot for the help |
| 01:04:14 | <roconnor> | dolio: augustss is the package author, but #haskell upgrades it. |
| 01:04:38 | <roconnor> | Cale: yes, but lambdabot doesn't come with nat. |
| 01:04:50 | <Cale> | I could add it... |
| 01:04:52 | <dolio> | Oh. |
| 01:05:26 | <roconnor> | Cale: nat's Enum instance is also 60% borked. |
| 01:05:31 | <Cale> | hmm |
| 01:05:47 | <aavogt> | Cale: how about StrictCheck in lambdabot too? |
| 01:05:52 | <roconnor> | Enum Nat really needs a proper full implementation to work properly. |
| 01:07:03 | <Cale> | aavogt: That seems like more work :) |
| 01:08:00 | <Cale> | @undefine |
| 01:08:21 | <Cale> | > (3 :: Nat) + 1 |
| 01:08:22 | <lambdabot> | /tmp/1017640965175325836:70:46: |
| 01:08:22 | <lambdabot> | Not in scope: type constructor or clas... |
| 01:08:25 | <Cale> | hmm |
| 01:11:58 | <copumpkin> | :k Nat |
| 01:11:59 | <lambdabot> | * |
| 01:12:06 | <copumpkin> | > 3 :: Nat |
| 01:12:07 | <lambdabot> | /tmp/1691783180983557560:70:41: |
| 01:12:07 | <lambdabot> | Not in scope: type constructor or clas... |
| 01:12:13 | <copumpkin> | that's odd |
| 01:12:37 | <ray> | different lambdabot pieces know about it i guess |
| 01:12:57 | <copumpkin> | yeah, but I remember someone using it earlier |
| 01:14:00 | <Smorg> | > [0..] == [1..] |
| 01:14:01 | <lambdabot> | False |
| 01:14:09 | <Smorg> | [0..] == [0..] |
| 01:14:13 | <Smorg> | > [0..] == [0..] |
| 01:14:28 | <lambdabot> | thread killed |
| 01:17:39 | <EvilTerran> | > 0 : undefined == 1 : undefined |
| 01:17:41 | <lambdabot> | False |
| 01:18:31 | <aavogt> | > let let = let in undefined |
| 01:18:33 | <lambdabot> | <no location info>: parse error on input `=' |
| 01:26:33 | <mmorrow> | > "[0..]" == "[0..]" |
| 01:26:33 | <lambdabot> | Terminated |
| 01:26:39 | <mmorrow> | hah |
| 01:26:45 | <EvilTerran> | O.o |
| 01:26:48 | <mmorrow> | > "[0..]" == "[0..]" |
| 01:26:49 | <lambdabot> | Terminated |
| 01:26:57 | <Cale> | mueval is not installed atm |
| 01:27:01 | <EvilTerran> | , "[0..]" == "[0..]" |
| 01:27:04 | <lunabot> | True |
| 01:27:35 | <Cale> | hmm |
| 01:28:03 | <mmorrow> | Cale: a "Segnentaion fault" would be amusing |
| 01:28:04 | <Cale> | @flush |
| 01:28:17 | <mmorrow> | *..message would be ... |
| 01:28:36 | <Cale> | aha, finally |
| 01:28:48 | <Cale> | I don't think I had enough memory to do the linking for it :) |
| 01:28:53 | <mmorrow> | heh |
| 01:29:04 | <mmorrow> | , eval "[0..]" |
| 01:29:09 | <lunabot> | <<[Integer]>> |
| 01:29:24 | <mmorrow> | , fromDynamic (eval "[0..]") :: Maybe [Integer] |
| 01:29:27 | <lunabot> | Just [0,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... |
| 01:29:56 | <mmorrow> | , eval "fromDynamic (eval \"[0..]\") :: Maybe [Integer]" |
| 01:29:59 | <lunabot> | <<Maybe [Integer]>> |
| 01:30:28 | <Cale> | damn seen state... |
| 01:30:55 | <Cale> | there we go... |
| 01:31:01 | <xoclipse> | i just wrote a very basic AIM client in haskell, anyone want to check it out? (its just console but does login and some other cool stuff) |
| 01:31:04 | <Cale> | Now, does it work? |
| 01:31:09 | <Cale> | > (2 :: Nat) + 1 |
| 01:31:17 | <Cale> | ... |
| 01:31:18 | <lambdabot> | 3 |
| 01:31:20 | <copumpkin> | woo! |
| 01:31:29 | <Cale> | Oh, right, it's joining channels, so it's slow :) |
| 01:31:38 | <copumpkin> | what does Nat buy us? |
| 01:31:52 | <Cale> | I'm not sure, but it ought to be more efficient than Natural |
| 01:32:01 | <copumpkin> | > (genericLength [1..]) > 3 |
| 01:32:10 | <lambdabot> | * Exception: stack overflow |
| 01:32:18 | <Cale> | > (genericLength [1..] :: Nat) > 3 |
| 01:32:24 | <lambdabot> | * Exception: stack overflow |
| 01:32:30 | <copumpkin> | whoops, that's what I meant :) |
| 01:32:33 | <Cale> | hmm |
| 01:33:06 | <mmorrow> | does genericLength do that? |
| 01:33:12 | <Cale> | I wonder... |
| 01:33:30 | <copumpkin> | is that Nat lazy? |
| 01:33:41 | <mmorrow> | oh, n/m i didn't see the 'Nat' |
| 01:33:41 | <Cale> | > Data.Number.Nat.length [1..] > 3 |
| 01:33:42 | <copumpkin> | I thought genericLength was just a fold of const . (+1) |
| 01:33:44 | <lambdabot> | * Exception: stack overflow |
| 01:33:48 | <Cale> | pff |
| 01:33:56 | <Cale> | > length [1,2,3] |
| 01:33:57 | <lambdabot> | Ambiguous occurrence `length' |
| 01:33:57 | <lambdabot> | It could refer to either `Data.List.... |
| 01:33:59 | <Cale> | blah |
| 01:34:04 | <Cale> | I'll have to import it qualified |
| 01:34:07 | <aavogt> | > (genericLength [1..] :: Nat) < 4 |
| 01:34:09 | <lambdabot> | * Exception: stack overflow |
| 01:34:40 | <Cale> | @undefine |
| 01:34:44 | <Cale> | > length [1,2,3] |
| 01:34:45 | <lambdabot> | Ambiguous occurrence `length' |
| 01:34:45 | <lambdabot> | It could refer to either `Data.List.... |
| 01:34:50 | <Cale> | wait, what? |
| 01:35:01 | <mmorrow> | i think it doesn't matter though that it's lazy, since you demand the result that can only be obtained by reaching the end of the list, so it goes.. |
| 01:35:02 | <Cale> | @undef |
| 01:35:15 | <Cale> | > length [1,2,3] |
| 01:35:16 | <lambdabot> | Ambiguous occurrence `length' |
| 01:35:16 | <lambdabot> | It could refer to either `Data.List.... |
| 01:35:19 | <Cale> | huh... |
| 01:35:28 | <mmorrow> | @type length |
| 01:35:29 | <lambdabot> | forall a. [a] -> Int |
| 01:35:35 | <mmorrow> | , length ?f |
| 01:35:36 | <lunabot> | luna: Unbound implicit parameter (?f::[a]) |
| 01:35:39 | <mmorrow> | > length ?f |
| 01:35:39 | <lambdabot> | Ambiguous occurrence `length' |
| 01:35:40 | <lambdabot> | It could refer to either `Data.List.... |
| 01:35:46 | <Cale> | oh, stupid |
| 01:35:52 | <Cale> | I have to change it in mueval too. |
| 01:36:54 | <Cale> | > length [1,2,3] |
| 01:36:57 | <lambdabot> | 3 |
| 01:37:02 | <Cale> | > Nat.length [1,2,3] |
| 01:37:03 | <lambdabot> | 3 |
| 01:37:49 | <Cale> | > compare (Nat.length [1..]) 3 |
| 01:37:50 | <lambdabot> | * Exception: stack overflow |
| 01:37:54 | <Cale> | odd |
| 01:37:54 | <mmorrow> | @type Nat |
| 01:37:55 | <lambdabot> | Not in scope: data constructor `Nat' |
| 01:38:00 | <mmorrow> | @type Nat.length |
| 01:38:01 | <lambdabot> | Couldn't find qualified module. |
| 01:38:08 | <mmorrow> | > Nat.length |
| 01:38:09 | <lambdabot> | Overlapping instances for Show ([a] -> Nat) |
| 01:38:09 | <lambdabot> | arising from a use o... |
| 01:38:12 | <Cale> | oh, yes, one more place I have to change things |
| 01:38:33 | <mmorrow> | , 1 :: Nat |
| 01:38:34 | <lunabot> | luna: Not in scope: type constructor or class `Nat' |
| 01:38:37 | <mmorrow> | > 1 :: Nat |
| 01:38:38 | <lambdabot> | /tmp/4402716139142980055:71:41: |
| 01:38:38 | <lambdabot> | Not in scope: type constructor or clas... |
| 01:38:54 | <Cale> | It really annoys me that just as I finally had all the imports in one place, someone changed things :) |
| 01:38:58 | <mmorrow> | i wonder why the stack overflow |
| 01:39:24 | <mmorrow> | oh, that was on an infinite list |
| 01:39:50 | <coCoconut> | Cale: Just when you get all the answers, they go and change all the questions? ;) |
| 01:40:34 | <Cale> | @undef |
| 01:40:41 | <Cale> | :t Nat.length |
| 01:40:42 | <lambdabot> | forall a. [a] -> Nat |
| 01:40:48 | <copumpkin> | ACTION watches StrictAnal and OccurAnal scroll by his screen |
| 01:41:22 | <Cale> | mmorrow: It still ought to work. |
| 01:42:07 | <Cale> | > (473893072198403712980473289140 :: Nat) * 43728914073289107498214 |
| 01:42:08 | <lambdabot> | /tmp/4023223342573982941:71:279: |
| 01:42:08 | <lambdabot> | Not in scope: type constructor or cla... |
| 01:42:15 | <Cale> | > (473893072198403712980473289140 :: Nat.Nat) * 43728914073289107498214 |
| 01:42:16 | <lambdabot> | 1259947102118438840 |
| 01:42:23 | <Cale> | errrrr |
| 01:42:35 | <Cale> | heh |
| 01:43:11 | <mmorrow> | weee |
| 01:44:03 | <Cale> | whaaaaaaaat |
| 01:44:11 | <copumpkin> | :o |
| 01:44:47 | <Cale> | @undefine |
| 01:44:50 | <Cale> | > (473893072198403712980473289140 :: Nat.Nat) * 43728914073289107498214 |
| 01:44:51 | <lambdabot> | 1259947102118438840 |
| 01:44:53 | <Cale> | > (473893072198403712980473289140 :: Nat) * 43728914073289107498214 |
| 01:44:54 | <lambdabot> | /tmp/2670833402401945774:71:279: |
| 01:44:54 | <lambdabot> | Not in scope: type constructor or cla... |
| 01:45:10 | <Cale> | Okay, I'm also confused about the required qualification thing. |
| 01:45:24 | <Cale> | Oh, right, it's semi-ignoring the imports in L.hs |
| 01:45:30 | <Cale> | hmm |
| 01:46:14 | <Cale> | well, whatever, it looks really broken anyway |
| 02:03:25 | <m3ga> | @PosixTime |
| 02:03:25 | <lambdabot> | Unknown command, try @list |
| 02:06:17 | <m3ga> | @list |
| 02:06:17 | <lambdabot> | http://code.haskell.org/lambdabot/COMMANDS |
| 02:06:40 | <Elly> | ACTION attempts to ram monads through her head |
| 02:08:03 | <copumpkin> | Elly: instead of explicitly trying to learn them, I'd recommend just playing with existing ones and getting a "sense" of them |
| 02:08:20 | <Elly> | I'm reading http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html, which is making sense so far |
| 02:15:01 | <mkaemmer> | a question about monad transformers: |
| 02:15:33 | <mkaemmer> | I have a state transformer: StateT (State StdGen Int) IO() |
| 02:15:48 | <mkaemmer> | and would like to print the random int... |
| 02:16:20 | <mkaemmer> | I don't think I'm going about this correctly. |
| 02:17:20 | <mkaemmer> | does anyone who understands what I'm trying to do have any suggestions? |
| 02:17:46 | <kpreid> | you have a state monad stuffed in the state of a StateT? I somehow doubt that's what you want |
| 02:17:47 | <Lemmih> | mkaemmer: StateT StdGen IO a? |
| 02:18:39 | <mkaemmer> | kpreid: you're probably right |
| 02:19:58 | <mkaemmer> | the question is... how can I keep track of two states (the int and the seed) and perform IO operations |
| 02:20:23 | <saml> | > (maxBound :: Int32) - (minBound :: Int32) |
| 02:20:25 | <lambdabot> | -1 |
| 02:20:48 | <saml> | > (maxBound :: Int32) - (minBound :: Int32) :: Int |
| 02:20:49 | <lambdabot> | Couldn't match expected type `Int' against inferred type `Int32' |
| 02:20:59 | <Elly> | hm... I am stuck on the "prove that lift f * lift g = lift (f . g)" part of http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html :( |
| 02:21:59 | <kpreid> | Elly: I would try substituting in the definition of lift on both sides, to start |
| 02:22:02 | <saml> | @pl \a b -> f a `g` f b |
| 02:22:02 | <lambdabot> | (. f) . g . f |
| 02:22:31 | <PetRat> | I'm reading Typeclassopedia. He suggests that implementing the ((->) e) monad is a good exercise for the reader. I am stumped. I read a bit about the State monad so I'm guessing there will be some kind of definition like newtype Reader e a = {runRead :: e->a}. Can someone confirm if this much is right? |
| 02:22:32 | <Gracenotes> | g `on` f |
| 02:22:35 | <Gracenotes> | @src on |
| 02:22:35 | <lambdabot> | (*) `on` f = \x y -> f x * f y |
| 02:22:37 | <Lemmih> | mkaemmer: StateT (StdGen,Int) IO a |
| 02:22:49 | <saml> | can I abstract it? |
| 02:22:51 | <saml> | oh |
| 02:22:55 | <Cale> | PetRat: You *could*, but I think the exercise is to define instance Monad ((->) e) where |
| 02:22:57 | <saml> | @hoogle on |
| 02:22:58 | <lambdabot> | Data.Function on :: (b -> b -> c) -> (a -> b) -> a -> a -> c |
| 02:22:58 | <lambdabot> | Text.PrettyPrint.HughesPJ OneLineMode :: Mode |
| 02:22:58 | <lambdabot> | Text.Parsec.Char oneOf :: Stream s m Char => [Char] -> ParsecT s u m Char |
| 02:23:15 | <Cale> | PetRat: that is, without a newtype |
| 02:23:26 | <PetRat> | Cale: then I need a clue. |
| 02:23:40 | <Cale> | PetRat: Okay, so one clue is that (->) e a = (e -> a) |
| 02:24:08 | <Cale> | and that in our type signatures the monad m is going to be replaced by (->) e |
| 02:24:28 | <mkaemmer> | Lemmih: that will probably work. Thanks :) |
| 02:24:35 | <Cale> | So if m is our monad we have, return :: a -> m a |
| 02:24:40 | <PetRat> | Hum, let me start with return. |
| 02:24:51 | <Cale> | So what will it become when we substitute for m? |
| 02:24:55 | <Elly> | kpreid: that step works, but then I have \x -> (f x, "") * \x -> (g x, "") = \x -> ((f . g) x, "") |
| 02:25:06 | <PetRat> | return x = \_ -> x ? |
| 02:25:11 | <PetRat> | or id? |
| 02:25:14 | <Elly> | ACTION tries expanding further |
| 02:25:18 | <Cale> | PetRat: well, yes, but what's the type? |
| 02:25:37 | <PetRat> | oh, a -> (e->a) |
| 02:25:40 | <Cale> | right |
| 02:25:48 | <kpreid> | Elly: Yes, that * would be the problem, I would guess. |
| 02:25:55 | <Cale> | Now, let's look at (>>=) :: m a -> (a -> m b) -> m b |
| 02:25:57 | <kpreid> | Elly: And at some point you can throw out the (, "") |
| 02:26:00 | <Cale> | what does its type become? |
| 02:26:01 | <kpreid> | (on both sides) |
| 02:26:08 | <Elly> | kpreid: I'm trying to get it to that point |
| 02:26:27 | <PetRat> | Okay, so >>= :: (m a) -> (a-> m b) -> m b. (e->a) -> (a->(e->b)) ->(e->b) |
| 02:26:32 | <Cale> | yep |
| 02:26:39 | <Cale> | So... |
| 02:26:46 | <Cale> | (x >>= f) e = ... |
| 02:27:08 | <PetRat> | oh it takes e as an argument? |
| 02:27:18 | <Cale> | well, it has 3 args, yeah? |
| 02:27:26 | <Gracenotes> | you could say x >>= f = \e -> ... |
| 02:27:28 | <Cale> | (before producing a value of type b) |
| 02:27:33 | <PetRat> | oh, also because the result is a function of e |
| 02:27:38 | <Cale> | right |
| 02:27:52 | <Cale> | So might as well have all the args on the left of the = |
| 02:28:10 | <Gracenotes> | combining a monad (function, in this case) with a function to the monad yields another monad (itself a function, in this case) |
| 02:28:16 | <Cale> | Gracenotes: eek! |
| 02:28:25 | <Cale> | Do not abuse the word monad! |
| 02:28:31 | <Cale> | hehe |
| 02:28:45 | <Cale> | There is only one monad here and it is ((->) e) |
| 02:28:54 | <PetRat> | does it make sense to drop the inner parenthesis and write (e->a) -> a -> (e->b) -> (e->b). Is that what you mean by three arguments? |
| 02:28:58 | <Gracenotes> | it is a polymorphic word >_> |
| 02:29:06 | <Cale> | PetRat: wrong parens |
| 02:29:17 | <Cale> | (e -> a) -> (a -> e -> b) -> e -> b |
| 02:29:29 | <Gracenotes> | (e->a) -> (a -> (e->b)) -> (e->b) |
| 02:29:31 | <Gracenotes> | also |
| 02:29:36 | <Gracenotes> | as you had above |
| 02:30:11 | <Cale> | (well, there is one monad for each e) |
| 02:30:30 | <Cale> | But the important thing is that a monad is something at the type level. |
| 02:30:49 | <Gracenotes> | yet, a monad instance is itself a type |
| 02:30:59 | <Gracenotes> | so how to refer to a value whose type is a monad instance? :) |
| 02:31:13 | <Cale> | A monadic value, computation or action |
| 02:31:20 | <Elly> | woohoo, I proved lift f * lift g = lift (f . g) |
| 02:31:30 | <MyCatVerbs> | "Action" is my favourite term for them. |
| 02:31:48 | <MyCatVerbs> | Monadic value is accurate but too wordy. :) |
| 02:32:09 | <MyCatVerbs> | "Computation" does not seem specific enough, IMO. |
| 02:33:23 | <Cale> | PetRat: Does that make sense, anyway? |
| 02:33:32 | <Cale> | PetRat: -> associates to the right |
| 02:34:07 | <Cale> | So (e -> a) -> ((a -> (e -> b)) -> (e -> b)) is the same as (e -> a) -> (a -> e -> b) -> e -> b |
| 02:34:51 | <Cale> | PetRat: Can you implement a function of that type? |
| 02:34:54 | <PetRat> | Yes. how about (winces) x >>= f = \e -> f (x e) e |
| 02:35:03 | <Cale> | right |
| 02:35:22 | <Cale> | So, there's basically only one way to do it, and that happens to give you a lovely monad. |
| 02:35:46 | <Cale> | > (do x <- id; y <- reverse; z <- map toUpper; return (x,y,z)) "hello" |
| 02:35:47 | <lambdabot> | ("hello","olleh","HELLO") |
| 02:36:06 | <Cale> | > join (*) 5 |
| 02:36:07 | <lambdabot> | 25 |
| 02:36:26 | <Cale> | > sequence [id,(+2),(*2),(^2),(2^)] 5 |
| 02:36:26 | <PetRat> | okay that wasn't too hard after I got unconfused. I wasn't sure what to do with 'e'. Note that in the line "instance Monad ((->) e)" e is a type variable, but I also used e as a value. |
| 02:36:27 | <lambdabot> | [5,7,10,25,32] |
| 02:36:38 | <Cale> | PetRat: oh, yes |
| 02:36:40 | <Cale> | e :: e |
| 02:36:43 | <Cale> | ;) |
| 02:36:53 | <PetRat> | Cale: are these demonstrations of the reader monad? |
| 02:37:02 | <Cale> | effectively |
| 02:37:12 | <Cale> | Though usually I just call this the function monad |
| 02:37:23 | <Cale> | and the wrapped up one Reader |
| 02:37:26 | <kpreid> | > (sequence $ map (\n -> iterate n drop) [0..5]) "hello" |
| 02:37:26 | <lambdabot> | Couldn't match expected type `(->) t' against inferred type `[]' |
| 02:37:49 | <kpreid> | > (sequence $ map drop [0..5]) "hello" |
| 02:37:50 | <lambdabot> | ["hello","ello","llo","lo","o",""] |
| 02:37:52 | <PetRat> | Oh I see. in the ("hello", ...) example each line is a function. |
| 02:37:57 | <BMeph> | kpreid: replicate, vice iterate, maybe? :) |
| 02:38:00 | <PetRat> | what is join? |
| 02:38:02 | <Cale> | PetRat: right |
| 02:38:19 | <kpreid> | BMeph: eh? |
| 02:38:21 | <Cale> | join x = do y <- x; v <- y; return v |
| 02:38:36 | <Cale> | join :: (Monad m) => m (m a) -> m a |
| 02:38:52 | <aavogt> | > mapM drop [0..5] "hello" |
| 02:38:53 | <lambdabot> | ["hello","ello","llo","lo","o",""] |
| 02:39:05 | <Cale> | Alternately, join x = x >>= id |
| 02:39:07 | <kpreid> | aavogt: ooh |
| 02:39:17 | <BMeph> | kpreid: Trying to figure out what "\n -> iterate n drop" was supposed to do. :) |
| 02:39:27 | <kpreid> | I was overdoing it |
| 02:39:36 | <kpreid> | "iterate n tail" |
| 02:39:38 | <PetRat> | Is there an intuitive description of join? |
| 02:40:00 | <copumpkin> | flattening a nested monad! |
| 02:40:00 | <Cale> | PetRat: Basically, if you have an action which produces another action as its result |
| 02:40:01 | <copumpkin> | ;) |
| 02:40:07 | <aavogt> | > tails "hello" |
| 02:40:09 | <lambdabot> | ["hello","ello","llo","lo","o",""] |
| 02:40:17 | <copumpkin> | aavogt: it's like being in a cave! |
| 02:40:21 | <Cale> | PetRat: Then you can construct an action which when run, runs this action, and then runs its result |
| 02:40:52 | <kpreid> | PetRat: For imperative-ish monads, it's "Figure out what to do, then do it" |
| 02:41:14 | <PetRat> | I see. (*) is a function of two arguments or in a curried sense a function of one argument which gives a function of one argument. |
| 02:41:20 | <kpreid> | join (return x) = x |
| 02:41:21 | <Cale> | PetRat: right :) |
| 02:41:48 | <Cale> | For containerish monads, it's often something like concatenation |
| 02:41:56 | <Cale> | > join [[1,2,3],[4,5],[6,7,8]] |
| 02:41:58 | <lambdabot> | [1,2,3,4,5,6,7,8] |
| 02:42:24 | <Cale> | Thinking of the list monad in terms of making selections, it first picks a list, then picks an element from it, in all possible ways |
| 02:42:34 | <Cale> | and that gives the concatenation of the lists :) |
| 02:43:02 | <PetRat> | Yes I've worked with the list monad a bit, from RWH, although I think moving over to Typeclassopedia is giving a better background for it. |
| 02:43:40 | <Cale> | > [y | x <- [[1,2,3],[4,5],[6,7,8]], y <- x] |
| 02:43:42 | <lambdabot> | [1,2,3,4,5,6,7,8] |
| 02:43:53 | <PetRat> | For all of RWH's 700 pages, when they get to monads and monad transformers it sure feels like they are racing through the material. |
| 02:43:54 | <Cale> | > do x <- [[1,2,3],[4,5],[6,7,8]]; y <- x; return y |
| 02:43:55 | <lambdabot> | [1,2,3,4,5,6,7,8] |
| 02:44:11 | <Cale> | Or even: |
| 02:44:15 | <Cale> | > do x <- [[1,2,3],[4,5],[6,7,8]]; x |
| 02:44:16 | <lambdabot> | [1,2,3,4,5,6,7,8] |
| 02:44:41 | <ray> | i think it's more that monads and monad transformers need a slower pace |
| 02:45:15 | <PetRat> | ray: that's what I was trying to say actually---that there's so much to learn about Haskell. |
| 02:45:21 | <Cale> | Monad transformers are a strange topic to approach. They're a library design technique more than they are an application programming technique. |
| 02:45:26 | <fynn> | Slightly offtopic, but what's a good resource (book, URL, whatever) for algorithms & data structures problems, preferably with solutions? |
| 02:45:44 | <ray> | monad transformers are weird |
| 02:45:44 | <fynn> | Ideally, something that would take a good solver 10-60 minutes to solve. |
| 02:46:08 | <ray> | sicp exercises? i dunno |
| 02:46:34 | <fynn> | I'm interviewing a guy for a job, and looking for some question ideas. |
| 02:46:59 | <fynn> | We're looking to use Haskell soon, so it's slightly on topic :> |
| 02:47:13 | <copumpkin> | purely functional data structures? |
| 02:47:15 | <lament> | ooooh hire me hire me |
| 02:47:37 | <roconnor> | no no hire me! |
| 02:47:37 | <fynn> | lament: your username suggests I shouldn't :/ |
| 02:47:46 | <roconnor> | lament couldn't program his way out of a paper bag |
| 02:47:52 | <fynn> | heh, PM me your resumes. |
| 02:47:53 | <copumpkin> | ACTION laments lament's lack of a job |
| 02:48:11 | <lament> | fynn: we can negotiate a username change if necessary ;) |
| 02:48:13 | <roconnor> | fynn: where is the job? |
| 02:48:14 | <copumpkin> | no no hire me! roconnor couldn't program his way out of a paper bag |
| 02:48:22 | <fynn> | roconnor: Bay area. |
| 02:48:29 | <roconnor> | ack! |
| 02:48:34 | <copumpkin> | besides, I have the coolest nick ev4r |
| 02:48:42 | <copumpkin> | and 1 wr1t3 1n l33t |
| 02:48:51 | <roconnor> | might as well hire copumpkin then. |
| 02:48:53 | <copumpkin> | ACTION b34mz |
| 02:48:56 | <fynn> | ooh, such class. |
| 02:49:00 | <ray> | monads would be so much easier to understand if the prelude let you define them with join |
| 02:49:08 | <fynn> | anyways, I'm still looking for good interview problems :| |
| 02:49:11 | <copumpkin> | ACTION b0wz |
| 02:49:16 | <roconnor> | fynn: I did the whole Berkeley grad school thing. |
| 02:49:22 | <copumpkin> | fynn: will they be programming problems or just conceptual? |
| 02:49:23 | <roconnor> | already |
| 02:49:33 | <fynn> | copumpkin: programming problems for sure. |
| 02:49:49 | <fynn> | the guys is pretty good, I need to know he can actually solve programming probelms. |
| 02:50:06 | <lament> | roconnor: damn |
| 02:50:08 | <lament> | ACTION folds |
| 02:50:11 | <fynn> | that said, they should also contain some theoretical challenge |
| 02:50:16 | <Cale> | This job demands fluent 13375p34k, and it is expected that applicants will file their resumes in it. |
| 02:50:21 | <copumpkin> | lol |
| 02:50:46 | <roconnor> | lament: if it helps, I dropped out of my PhD program at Berkeley. |
| 02:50:55 | <copumpkin> | roconnor: why? |
| 02:50:56 | <ray> | and people complain about resumes that have to be in word |
| 02:51:10 | <lament> | roconnor: to get a masters? |
| 02:51:13 | <roconnor> | copumpkin: they have no intrest in dependent type theory there. |
| 02:51:15 | <copumpkin> | yeah, resumes must be .nfo files with l33tspeak and ascii art |
| 02:51:20 | <lament> | roconnor: isn't that the usual swindle anyhow? |
| 02:51:30 | <copumpkin> | roconnor: there seems to be less interesting PL in the US in general, I've found |
| 02:51:33 | <roconnor> | ... interdisciplinary logic program my ass |
| 02:51:51 | <ray> | resumes must be in the form of a bittorrent ratio, references from at least 2 private torrent trackers required |
| 02:51:57 | <fynn> | you guys are so not helpful :> |
| 02:52:01 | <copumpkin> | fynn: aw, sorry |
| 02:52:09 | <copumpkin> | fynn: try purely functional datastructures though |
| 02:52:09 | <fynn> | hehe, it's OK, I have more than enough questions. |
| 02:52:17 | <fynn> | just wondering if you have any good suggestions. |
| 02:52:22 | <roconnor> | fynn: ask him to write a memoized list of prime numbers generator. |
| 02:52:26 | <roconnor> | in haskell |
| 02:52:35 | <fynn> | roconnor: I actually thought about that particular problem. |
| 02:52:49 | <ray> | ask him to write a haskell numeric prelude |
| 02:52:54 | <copumpkin> | fynn: are you just trying to find out if they know what they're talking about when it comes to haskell? |
| 02:52:55 | <fynn> | the candidate is very good at math, so I don't want to play to his strengths. |
| 02:52:58 | <copumpkin> | or a deep thinking problem? |
| 02:53:13 | <roconnor> | fynn: I think that primes problem separates the haskell n00bs from the slightly less newbies. |
| 02:53:20 | <fynn> | copumpkin: the latter. we plan to integrate Haskell, but knowing Haskell now is not a requirement. |
| 02:53:25 | <copumpkin> | I see |
| 02:53:54 | <lament> | fynn: mad props for using haskell! |
| 02:54:18 | <fynn> | the guy has a PhD from a math related field, so I'm mainly going to see how he handles CS theory, and ultimately also solving a hard problem with actual code. |
| 02:54:43 | <roconnor> | fynn: is his name Josh? |
| 02:54:48 | <fynn> | he's placed well in math competitions etc, I'm not concerned that he is dumb, but I am concerned he may be too detached. |
| 02:55:05 | <fynn> | i.e. unable to solve practical problems and actually code. |
| 02:55:26 | <fynn> | lament: thanks. we were using Python, and looking for something stateless and fun, so Haskell seemed a good choice :) |
| 02:55:51 | <roconnor> | heh, inability to solve practical problems could be a general problem with Haskell programmers :P |
| 02:56:07 | <ray> | no way, there's language communities that are a lot worse |
| 02:56:23 | <fynn> | roconnor: well, it wouldn't fly here, that's for sure =) |
| 02:56:39 | <lament> | fynn: then don't ask algorithms questions, ask practical questions |
| 02:56:40 | <roconnor> | fynn: how long is the interview? |
| 02:56:49 | <fynn> | roconnor: 60-90 minutes. |
| 02:56:52 | <BMeph> | ACTION coughs: *Smalltalk!* Man, these spring colds are the worst! ;p |
| 02:56:53 | <roconnor> | hmm |
| 02:57:13 | <ray> | my cough sounds like "common lisp" for some reason |
| 02:57:20 | <lament> | fynn: memoized primes are hardly a practical problem |
| 02:57:56 | <ray> | memoizing in general |
| 02:58:15 | <fynn> | lament: my current plan is: first 30 minutes - rapid fire knowledge questions about practical topics (operating systems, concurrency, concrete programming language aspects, how data structure are implemented in practice), and rapid fire "code a solution to a fairly trivial problem" |
| 02:58:25 | <roconnor> | fynn: I'm pondering some if the ICFP contest puzzle problems from 2006, but they might be too hard. |
| 02:58:47 | <fynn> | rest 60 minutes: 1-3 truly complex questions, and he has to code a solution. |
| 02:59:08 | <copumpkin> | ACTION screams at libffi |
| 02:59:10 | <roconnor> | code a solution in what language? |
| 02:59:15 | <fynn> | roconnor: definitely; a question may not take more than 60 minutes total, and I want to see semi-working code on the board. |
| 02:59:19 | <fynn> | whatever language he likes. |
| 03:00:10 | <roconnor> | how hard was that plinko problem? ... but it was kinda math related. |
| 03:00:12 | <roconnor> | oh |
| 03:00:19 | <roconnor> | how about those google treasure hunt problems |
| 03:00:29 | <fynn> | never heard for that, I'll look at it. |
| 03:00:30 | <roconnor> | they were ridicuously easy. |
| 03:00:39 | <roconnor> | at least I found |
| 03:00:47 | <roconnor> | ... some of the solutions reddit came up with |
| 03:00:52 | <roconnor> | ACTION shakes his head |
| 03:01:07 | <fynn> | heh. candidates in the past complained our questions were too easy :) |
| 03:01:20 | <fynn> | at least one good guy we hired thought they were. |
| 03:01:21 | <copumpkin> | fynn: are you allowed to tell us what company that is? |
| 03:01:34 | <fynn> | copumpkin: not really, and we're a startup :) |
| 03:02:32 | <copumpkin> | ah :) |
| 03:03:05 | <roconnor> | you could ask him to implement a bag data type, and then implement a set data type reusing the bag code. |
| 03:03:19 | <roconnor> | and sees if he screws it up. |
| 03:03:41 | <fynn> | even in this area (MTV / Palo Alto and the neighborhood) I don't know of companies using Haskell |
| 03:03:42 | <roconnor> | ACTION remembers reading Oleg's essay on that last week. |
| 03:03:55 | <fynn> | I heard of one other startup that does, but don't know too much about them. |
| 03:05:35 | <roconnor> | http://okmij.org/ftp/Computation/Subtyping/ |
| 03:05:48 | <fynn> | in any case, thanks for your input. I'm sure you were mostly joking; doubt anyone here has a serious problem getting a job ;) |
| 03:06:06 | <roconnor> | hopefully I will get my fellowship |
| 03:06:10 | <roconnor> | then i won't need a job |
| 03:06:34 | <lament> | fynn: getting a job is one thing |
| 03:06:41 | <m3ga> | i'm coding on Linux and using Hoogle, but find that Hoogle is missing a bunch of stuff. ie System.Time. Is there an alternative to Hoogle that covers Linux/Posix stuff better? |
| 03:06:45 | <lament> | getting a haskell job is quite another :) |
| 03:07:02 | <roconnor> | lament: good point |
| 03:07:13 | <roconnor> | @hoogle Time |
| 03:07:13 | <lambdabot> | module Data.Time |
| 03:07:13 | <lambdabot> | package time |
| 03:07:13 | <lambdabot> | Data.Time.LocalTime data TimeOfDay |
| 03:07:21 | <roconnor> | @hoogle+ |
| 03:07:21 | <lambdabot> | Data.Time.LocalTime TimeOfDay :: Int -> Int -> Pico -> TimeOfDay |
| 03:07:21 | <lambdabot> | Data.Time.LocalTime timeOfDayToDayFraction :: TimeOfDay -> Rational |
| 03:07:21 | <lambdabot> | Data.Time.LocalTime timeOfDayToTime :: TimeOfDay -> DiffTime |
| 03:07:25 | <roconnor> | hmm |
| 03:07:29 | <roconnor> | @hoogle posix |
| 03:07:29 | <lambdabot> | module Data.Time.Clock.POSIX |
| 03:07:29 | <lambdabot> | module System.FilePath.Posix |
| 03:07:29 | <lambdabot> | package posix-realtime |
| 03:07:32 | <fynn> | lament: true, hopefully the selection would increase as time goes by. |
| 03:07:43 | <lament> | m3ga: try hayoo |
| 03:07:44 | <m3ga> | @hoogle System.Time |
| 03:07:44 | <lambdabot> | package time |
| 03:07:44 | <lambdabot> | module System.Timeout |
| 03:07:44 | <lambdabot> | System.Timeout timeout :: Int -> IO a -> IO (Maybe a) |
| 03:07:55 | <lament> | m3ga: http://holumbus.fh-wedel.de/hayoo/hayoo.html |
| 03:08:06 | <roconnor> | I wonder if it is that System.Time is depricated? |
| 03:08:14 | <fynn> | there's certainly more awareness now, especially with more tools maturing, e.g. the Haskell Platform. |
| 03:08:25 | <fynn> | (and Hackage, Cabal, etc.) |
| 03:08:40 | <fynn> | more *practical |
| 03:09:05 | <m3ga> | lament: thanks, interface not quiet as nice but it works |
| 03:09:23 | <roconnor> | fynn: if I don't get my fellowship, you should move your start-up to Waterloo Ontario. |
| 03:09:27 | <roconnor> | :P |
| 03:09:43 | <m3ga> | roconnor: i think the problem os that hoogle run on windows and hence can't query packages that only run on Posix |
| 03:10:04 | <roconnor> | m3ga: I don't think that is the case, but I'm not sure. |
| 03:10:11 | <fynn> | roconnor: you can easily work remotely from there for some American companies :) |
| 03:10:29 | <roconnor> | http://www.haskell.org/hoogle/?hoogle=posix |
| 03:10:46 | <roconnor> | perhaps. |
| 03:11:14 | <fynn> | btw, how can one "not get a fellowship"? |
| 03:11:37 | <roconnor> | fynn: there are only a certain number of fellowships available. |
| 03:12:21 | <fynn> | roconnor: can't you just go on a PhD program anyway? |
| 03:12:43 | <roconnor> | this is a post-doctoral fellowship |
| 03:12:47 | <roconnor> | oh |
| 03:12:58 | <roconnor> | right, after dropping out at Berkeley I went to the Netherlands |
| 03:13:07 | <roconnor> | where they actually do research into type theory |
| 03:13:16 | <fynn> | ah, I thought you didn't finish your PhD |
| 03:13:29 | <gwern> | @quote PhD |
| 03:13:30 | <lambdabot> | ghc says: You can get a PhD for explaining the True Meaning of this last construct |
| 03:13:38 | <roconnor> | fynn: ya, sorry for misleading you. |
| 03:13:41 | <gwern> | @quote PhD |
| 03:13:41 | <lambdabot> | dons says: so, anyone else plan on getting a phd in haskell studies, so they can get a job at a big investment bank? :) |
| 03:13:50 | <gwern> | hm. |
| 03:13:52 | <gwern> | @quote PhD |
| 03:13:52 | <lambdabot> | dons says: so, anyone else plan on getting a phd in haskell studies, so they can get a job at a big investment bank? :) |
| 03:13:52 | <roconnor> | that was my plan |
| 03:13:56 | <roconnor> | untill last year. |
| 03:13:59 | <roconnor> | :) |
| 03:14:03 | <gwern> | heh |
| 03:14:08 | <gwern> | jane street' still around |
| 03:14:13 | <roconnor> | yep |
| 03:14:16 | <fynn> | heh, what happened last year? |
| 03:14:22 | <gwern> | I'm sure ocaml wouldn't be *too* painful... |
| 03:14:29 | <roconnor> | every big investment bank went under. |
| 03:14:36 | <m3ga> | jane street say they quite like the current market |
| 03:14:38 | <gwern> | fynn: the tide went out, per buffett |
| 03:14:53 | <gwern> | m3ga: I guess, if they had enough cash to spare to fund haskell projects |
| 03:15:08 | <roconnor> | jane street isn't a big investment bank. :) |
| 03:15:17 | <fynn> | gwern: mhm, yeah, I can understand what you mean |
| 03:15:22 | <fynn> | but what roconnor just said |
| 03:15:35 | <fynn> | though it certainly didn't help the entire market. |
| 03:16:02 | <fynn> | but sure, lots of laid off financial programmers now seeking employment in different areas. |
| 03:16:12 | <lament> | and not just financial |
| 03:16:25 | <lament> | microsoft laid off thousands of people |
| 03:16:31 | <gwern> | (a good fund should be able to profit off the volatility and general chaos, but who knows how many of those there are) |
| 03:16:33 | <roconnor> | heh, especially since the disaster was "all their fault" |
| 03:16:47 | <gwern> | lament: which was a little odd, since MS has tons of money and just raised billions more |
| 03:16:55 | <fynn> | lament: only few of them actual programmers, no? |
| 03:17:01 | <roconnor> | MS raises money? |
| 03:17:17 | <lament> | dunno the numbers |
| 03:17:28 | <gwern> | roconnor: oh sure. a few days ago they finished up a multi-billion $ bond offer |
| 03:17:33 | <fynn> | rumor is, lots of places that are firing, including MS, are just using the events as execuses to get rid of dead wood. |
| 03:17:52 | <gwern> | made headlines because this apparently is the first time MS has ever sought outside capital like that |
| 03:18:14 | <gwern> | people're interested because it looks like a move most useful if they're going after yahoo again |
| 03:18:43 | <lament> | yahoo should get a restraining order against them |
| 03:18:55 | <fynn> | they probably will. I doubt they'll stop until they acquire one giant web hub. |
| 03:19:03 | <fynn> | and not too many of those around. |
| 03:19:16 | <lament> | at least google isn't in any danger at the moment |
| 03:19:26 | <lament> | and yahoo, who really cares :) |
| 03:19:35 | <fynn> | there's absolutely no reason why they would be prevented from buying yahoo. it's a quirk they weren't able to in the first place. |
| 03:19:37 | <gwern> | heh. no, eric schmidt sounded quite upbeat this weekend |
| 03:19:39 | <ttmrichter> | Is there anybody connected who knows anything about porting GHC to a currently unsupported platform? The docs available are out of date and specifically say they don't apply to any version past 6.4. |
| 03:19:47 | <gwern> | (he was speaking at the CMU commencement) |
| 03:20:08 | <dmwit> | ttmrichter: You might want to hang around in #ghc. |
| 03:20:09 | <sclv> | what platform? |
| 03:20:31 | <ttmrichter> | dmwit: Ah! Didn't know it existed. sclv: OpenSolaris. |
| 03:20:39 | <gwern> | ttmrichter: might try the ghc channel. my understanding is that the procedure is to take one of the old bootstrapping ghcs, and then compile ghcs until you've gotten up to something new |
| 03:20:54 | <copumpkin> | ttmrichter: it's mostly supported now in 6.11 again |
| 03:20:55 | <gwern> | ttmrichter: also, solaris? there's a blog about getting ghc running on sparc |
| 03:21:00 | <sclv> | there's been lots of solaris work done lately, as i recall. |
| 03:21:08 | <ttmrichter> | gwern: OpenSolaris x86, not Sparc. |
| 03:21:40 | <ttmrichter> | But if GHC is being moved to Solaris already, perhaps waiting is better than driving myself insane with the bootstrapping. :D |
| 03:22:02 | <sclv> | i'd search the -cafe archives? i seem to recall donn cave did some work a few mos back? |
| 03:22:33 | <sclv> | if the archives confirm my recollections you could try contacting him directly and see what he has working at the moment too. |
| 03:23:26 | <roconnor> | gwern: ah, bonds. That makes sense. |
| 03:23:51 | <gwern> | well sure. how else would they raise money? |
| 03:24:59 | <roconnor> | gwern: um .. venture capital? |
| 03:25:02 | <roconnor> | :P |
| 03:25:22 | <roconnor> | gwern: more seriously, issuing new stock |
| 03:25:33 | <gwern> | ? and who precisely would be giving the VC stock? why would existing shareholders authorize dilution? |
| 03:25:35 | <roconnor> | but both those seem completely implausible. |
| 03:25:43 | <roconnor> | hence my question. |
| 03:41:31 | <amckinley> | hey, parsec question: im parsing bind config files, which have the incredibly annoying property that if you omit the hostname for a record, the record assumes the hostname of the previous record. i have no idea how to modify my more-or-less line oriented parser to handle that case |
| 03:42:19 | <dmwit> | Use Parsec's state. |
| 03:42:35 | <dmwit> | It's got "get" and "set" functions. |
| 03:44:28 | <amckinley> | dmwit: can you give me a little more guidance? im still new to haskell |
| 03:45:38 | <dmwit> | http://legacy.cs.uu.nl/daan/download/parsec/parsec.html#getState |
| 03:45:51 | <dmwit> | When you read a hostname, set the state using setState. |
| 03:46:06 | <dmwit> | If you read a record with no hostname, set it to the current state by calling getState. |
| 03:46:51 | <dmwit> | You could also just read the records in, record which ones didn't have a hostname, and fill them in after the entire parsing stage was done. |
| 03:47:16 | <dmwit> | (Which wouldn't require the getState/setState functions at all.) |
| 03:48:43 | <amckinley> | dmwit: i was under the impression that parsec's state was for deep internal parsec magic. are you saying you can put arbitrary state in it? |
| 03:48:56 | <dmwit> | There's parsec state and user state. |
| 03:49:04 | <dmwit> | getState/setState/updateState modify the user state |
| 03:49:13 | <amckinley> | ahhhhh, gotcha |
| 03:50:32 | <amckinley> | thanks a bunch |
| 03:54:46 | <roconnor> | @hoogle ReaderT r m a -> StateT r m a |
| 03:54:46 | <lambdabot> | No results found |
| 03:54:49 | <roconnor> | :( |
| 03:57:07 | <grncdr> | what is the deal with Int vs. Integer? |
| 03:57:19 | <grncdr> | <- total haskell noob |
| 03:57:31 | <roconnor> | > maxBound :: Int |
| 03:57:32 | <lambdabot> | 9223372036854775807 |
| 03:57:35 | <roconnor> | > maxBound :: Intenger |
| 03:57:36 | <lambdabot> | Not in scope: type constructor or class `Intenger' |
| 03:57:42 | <roconnor> | > maxBound :: Integer |
| 03:57:43 | <lambdabot> | No instance for (Bounded Integer) |
| 03:57:43 | <lambdabot> | arising from a use of `maxBoun... |
| 03:57:51 | <roconnor> | , maxBound :: Int |
| 03:57:52 | <lunabot> | 2147483647 |
| 03:58:00 | <roconnor> | > 2^100 :: Int |
| 03:58:01 | <lambdabot> | 0 |
| 03:58:01 | <grncdr> | ah I see |
| 03:58:04 | <roconnor> | > 2^100 :: Integer |
| 03:58:05 | <lambdabot> | 1267650600228229401496703205376 |
| 04:16:51 | <jbhatta> | i'm trying to use getopts. the examples i've found suggest that the best way to take care of options with arguments is to wrap them in a type that encapsulates the argument |
| 04:17:34 | <jbhatta> | and then make a type that can hold any one of the types i just made so i can have a list of 'em |
| 04:18:13 | <jbhatta> | but now i've got a list of these things, and i don't really know how to deal with them functionally. i need to do different things with different options, but sometimes multiple options interact, etc |
| 04:18:42 | <jbhatta> | is there some kind of trick that i should be aware of, or do i need to write a bunch of exhaustive function definitions matching each possible pattern combination or something awful like that? |
| 04:20:04 | <jbhatta> | i'm sure i don't have to do something that awful, because i doubt that this community would endorse a getopts implementation that forced them to do something that ugly |
| 04:20:23 | <jbhatta> | but i'm new to haskell, so the best solution is far from obvious to me |
| 04:21:01 | <bos> | jbhatta: i think there's an example in RWH |
| 04:21:21 | <MyCatVerbs> | Usually you want something like, data Flag = ConfigFile FilePath | DebugMode Bool... |
| 04:22:06 | <pumpkin> | thoughtpolice: *poke* |
| 04:22:09 | <jbhatta> | MyCatVerbs: i've done that, but now i've got a list of flags from getopts and i'm not sure how to process them |
| 04:22:41 | <jbhatta> | MyCatVerbs: for example, i have one switch that takes no arguments that will call a different function to do the main work |
| 04:22:53 | <jbhatta> | and one required option with an argument pointing to a config file |
| 04:23:29 | <jbhatta> | i always want to read that required option, but once i do, i want to use its argument when i call the function picked by specifying the other option (the "switch" i mentioned) |
| 04:24:44 | <MyCatVerbs> | jbhatta: hol' up. You *are* using System.Console.GetOpt, rather than raw GetArgs? |
| 04:25:06 | <jbhatta> | MyCatVerbs: yeah, i am |
| 04:25:20 | <MyCatVerbs> | Right. So that handles required or non-required arguments for you. |
| 04:25:37 | <jbhatta> | i think my problem is so basic that it's difficult to describe |
| 04:25:49 | <jbhatta> | i'm going to get a list from getopts of flags |
| 04:25:55 | <MyCatVerbs> | The list it hands back to you is just what you'd get it you repeatedly called getopt(3) in C. |
| 04:26:15 | <MyCatVerbs> | (Well, in spirit anyway). |
| 04:27:19 | <MyCatVerbs> | You can do things like scan the list for all of the instances of a particular option, remove those and set flags of some description... |
| 04:29:03 | <jbhatta> | hmmm, i didn't think to actively scan the list looking for options |
| 04:29:03 | <MyCatVerbs> | e.g. (options,nonoptions,errors) <- getOpt Permute optionspec args |
| 04:29:32 | <MyCatVerbs> | let debugMode = elem (DebugMode True) options |
| 04:30:14 | <jbhatta> | ah, ok |
| 04:30:19 | <MyCatVerbs> | let filesToFoo = [ file | (Foo file) <- options ] |
| 04:30:35 | <MyCatVerbs> | mapM foo filesToFoo -- :) |
| 04:31:21 | <MyCatVerbs> | (That list comprehension is just a map and filter together. Extracts all the Foo elements from options.) |
| 04:31:59 | <jbhatta> | ah, ai see what u did thar |
| 04:32:02 | <jbhatta> | what's mapM? |
| 04:32:19 | <MyCatVerbs> | Er, should usually be mapM_. mapM = sequence . map |
| 04:32:37 | <MyCatVerbs> | sequence takes a list of actions, and runs them one after another. |
| 04:32:58 | <jbhatta> | is it kinda like fold? |
| 04:33:03 | <jbhatta> | what type do "actions" have? |
| 04:33:11 | <jbhatta> | functions returning monadic types or something? |
| 04:33:20 | <MyCatVerbs> | When I say "actions" I'm talking about monadic values. |
| 04:33:31 | <jbhatta> | ah, ok, spiffy |
| 04:33:44 | <MyCatVerbs> | sequence :: (Monad m) => [m a] -> m [a] |
| 04:34:19 | <jbhatta> | whoa, ok |
| 04:34:25 | <MyCatVerbs> | e.g. mapM putStrLn ["foo","bar","baz"] -- prints "foo\nbar\nbaz\n" to stdout, and returns [(),(),()] because putStrLn's result is always (). |
| 04:34:58 | <jbhatta> | MyCatVerbs: gotcha. cool, ok, so i'm learning a lot today |
| 04:34:58 | <jbhatta> | hehe |
| 04:35:20 | <MyCatVerbs> | mapM_ putStrLn ["foo","bar","baz"] -- is another IO action that does the same thing, but returns just (), which isn't much less useful than [(),(),()]. :) |
| 04:35:52 | <jbhatta> | does it return the last thing it evaluates or something? |
| 04:35:56 | <MyCatVerbs> | mapM_ is useful when you don't care about the return values, because mapM_ never needs to hold on to them, so the garbage collector can just throw the return values away right away. |
| 04:36:03 | <jbhatta> | ah, ok |
| 04:36:13 | <jbhatta> | so it just ALWAYS returns () |
| 04:36:16 | <MyCatVerbs> | Ah, no. I should've explained that. It throws *all* the results away. |
| 04:36:22 | <MyCatVerbs> | @type mapM_ |
| 04:36:23 | <lambdabot> | forall a (m :: * -> *) b. (Monad m) => (a -> m b) -> [a] -> m () |
| 04:36:49 | <jbhatta> | ok |
| 04:37:21 | <MyCatVerbs> | It takes actions of all types, runs them, then sends the results away to die lonely and unloved in the middle of the Australian Great Bugger All. |
| 04:37:36 | <jbhatta> | hehehe |
| 04:37:45 | <MyCatVerbs> | Er, any, not all. You won't usually get too far with a mixed list. >> |
| 04:40:12 | <MyCatVerbs> | jbhatta: mapM_ foo filesToFoo is just a convenient way to write: let { fooAllFiles (file:files) = foo file >> fooAllFiles; fooAllFiles [] = return (); } in fooAllFiles filesToFoo |
| 04:40:38 | <MyCatVerbs> | jbhatta: I hope you'll agree that it's a lot more convenient to use the short combinators for the simple cases. |
| 04:41:02 | <jbhatta> | oh yes, absolutely |
| 04:41:17 | <jbhatta> | i'm just a n00b, so i end up looking stuff up pretty frequently |
| 04:41:31 | <MyCatVerbs> | @where hoogle |
| 04:41:31 | <lambdabot> | http://haskell.org/hoogle |
| 04:41:43 | <jbhatta> | ah yes. i have learned of the magic of hoogle |
| 04:42:28 | <MyCatVerbs> | jbhatta: I still rarely do anything much without the haddock docs at hand. ^^ |
| 04:43:11 | <jbhatta> | yeah, it's tricky. luckily haskell is weirdly natural to document |
| 04:43:12 | <jbhatta> | hehe |
| 04:43:25 | <jbhatta> | so i've seen thus far, anyway |
| 04:43:48 | <jbhatta> | i'm using xmonad, and the xmonad libraries are freaking HUGE |
| 04:43:57 | <jbhatta> | but it's still pretty easy to look things up and figure them out |
| 04:44:06 | <jbhatta> | thankfully! |
| 04:44:14 | <dmwit> | Yay! |
| 04:44:21 | <jbhatta> | :-D |
| 04:44:22 | <dmwit> | This is AWEsome praise! |
| 04:44:52 | <jbhatta> | dmwit: do you maintain or just advocate the xmonad docs? ;) |
| 04:45:21 | <dmwit> | Well, there's been a lot of talk recently about improving the docs for Haskell libraries. |
| 04:45:28 | <dmwit> | So if somebody finds some of them good... =) |
| 04:46:30 | <jbhatta> | hehehe. i like their consistent format, and haskell's type declarations are just so good you can usually just read the types and the name of the function and it's nice. but then there's a description at the end of the doc just in case! |
| 04:46:34 | <jbhatta> | i think it's pretty nice |
| 04:48:37 | <hatds> | agreed |
| 04:49:15 | <jbhatta> | and it's also nice that you guys seem friendlier than some of the lisp guys i got used to dealing with ;) |
| 04:49:23 | <hatds> | and random unfamiliar source in the libraries is often easy to read too |
| 04:49:45 | <hatds> | :) |
| 04:51:34 | <roconnor> | in #haskell we don't pretend to even know how to program properly yet. :) |
| 04:51:59 | <p_l> | jbhatta: we no longer bite, believe me (well, I'd recommend staying away from c.l.l, no matter your level, aptitude etc.) |
| 04:52:19 | <pumpkin> | ChilliX: I think I have a ghc x86_64 for mac os almost working! |
| 04:52:29 | <MyCatVerbs> | p_l: "no longer"? I didn't think we ever bit much at any point? :/ |
| 04:52:47 | <p_l> | MyCatVerbs: I spoke as #lisp denizen ;P |
| 04:53:17 | <MyCatVerbs> | p_l: oh, phew. |
| 04:53:26 | <jbhatta> | p_l: ah, well that's good to hear! |
| 04:53:32 | <jbhatta> | i admit i was kinda scared off |
| 04:53:33 | <jbhatta> | hehe |
| 04:54:22 | <roconnor> | p_l: I find it hard to believe #lisp is that bad, yet I hear so many stories. |
| 04:54:25 | <p_l> | ACTION also heard tales of how #lisp was a scary place... but it's no longer (unless you troll). comp.lang.lisp is a loss of time, IMHO |
| 04:55:19 | <rickasauruss> | I hoogle all my searches |
| 04:55:26 | <p_l> | and well, stupid questions are not welcome, and sometimes you can make them even by mistake :) |
| 04:56:14 | <jbhatta> | p_l: yeah, i'm known to do that pretty often. that was probably my downfall in #lisp |
| 04:58:08 | <lament> | is rahul in #lisp? |
| 05:01:08 | <p_l> | lament: I don't recognize that nick |
| 05:03:30 | <lament> | amazing |
| 05:03:36 | <Adamant> | #lisp is fine, it was never particularly bad. c.l.l is a cesspit. |
| 05:04:16 | <Adamant> | and #haskell is very nice and welcoming of newcomers. |
| 05:05:06 | <mintsoup> | are haskell guards dijkstra guards? like, if more than one is true is one branch chosen nondeterministically? |
| 05:05:06 | <MyCatVerbs> | Slightly more so than it was a couple months back, even. |
| 05:05:18 | <dmwit> | mintsoup: no |
| 05:05:19 | <MyCatVerbs> | mintsoup: no. They're more like Prolog pattern matches. |
| 05:05:24 | <Saizan> | mintsoup: the first one is chosen |
| 05:05:31 | <MyCatVerbs> | mintsoup: they're tried in order from top to bottom, and the first matching one is used. |
| 05:05:33 | <dmwit> | mintsoup: The first matching guard is chosen, with "first" being defined syntactically. |
| 05:06:00 | <mintsoup> | thanks |
| 05:15:28 | <jbhatta> | gawd, curried functions are definitely the best thing ever |
| 05:16:25 | <jbhatta> | so FREAKING handy |
| 05:16:45 | <jbhatta> | yaaay for this language |
| 05:17:34 | <araujo> | @yarr! |
| 05:17:34 | <lambdabot> | Arrr! |
| 05:30:37 | <mushtar> | Can we extract the contents of a monad by using a function, contents m = (m >>= id) ? |
| 05:30:48 | <pumpkin> | :t (>>=) |
| 05:30:50 | <lambdabot> | forall (m :: * -> *) a b. (Monad m) => m a -> (a -> m b) -> m b |
| 05:31:17 | <pumpkin> | :t \m -> m >>= id |
| 05:31:18 | <lambdabot> | forall (m :: * -> *) b. (Monad m) => m (m b) -> m b |
| 05:31:21 | <pumpkin> | :) |
| 05:31:23 | <sjanssen> | @type join |
| 05:31:24 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => m (m a) -> m a |
| 05:31:33 | <mushtar> | hm |
| 05:31:37 | <mushtar> | and how do you write join? |
| 05:31:42 | <pumpkin> | exactly as you did |
| 05:32:02 | <shachaf> | mushtar: A monad doesn't have "contents". |
| 05:32:04 | <pumpkin> | > let contents m = (m >>= id) in contents [[1,2,3], [4,5,6]] |
| 05:32:05 | <lambdabot> | [1,2,3,4,5,6] |
| 05:32:07 | <pumpkin> | ! |
| 05:32:08 | <pumpkin> | :) |
| 05:32:09 | <shachaf> | > fromJust Nothing |
| 05:32:10 | <lambdabot> | * Exception: Maybe.fromJust: Nothing |
| 05:32:15 | <mushtar> | shachaf: Why does a monad not have "contents"? |
| 05:32:24 | <shachaf> | Because you're confusing types and values, for one. |
| 05:32:31 | <pumpkin> | mushtar: what would contents of [1,2,3] be? |
| 05:32:31 | <shachaf> | Just x is not a monad; Maybe is. |
| 05:33:05 | <mushtar> | Hm I see |
| 05:33:33 | <pumpkin> | certain monads might have functions for pulling a value "out of them" |
| 05:33:36 | <pumpkin> | but in general it isn't possible |
| 05:33:46 | <pumpkin> | because for many monads it doesn't make sense |
| 05:33:55 | <mushtar> | so in general you can't run a monad, but if you have a monad inside a monad, you can extract that inner monad? |
| 05:34:07 | <mushtar> | even without having a function that pulls the value out? |
| 05:34:13 | <shachaf> | Not "out of the monad", but "out of values whose type is the monad" |
| 05:34:20 | <shachaf> | (Or at least that's closer.) |
| 05:34:28 | <mushtar> | yes |
| 05:34:42 | <shachaf> | mushtar: You can't extract anything from a monad. |
| 05:34:47 | <shachaf> | > join (Just Nothing) |
| 05:34:49 | <lambdabot> | Nothing |
| 05:34:56 | <Cale> | If you want, the contents of a monad are all the types which belong to it. |
| 05:34:58 | <mushtar> | so join has type m (m a) -> m a. but it does this without ever running the monad? |
| 05:34:59 | <shachaf> | > join (Nothing :: Maybe (Maybe Int)) |
| 05:35:00 | <lambdabot> | Nothing |
| 05:35:15 | <pumpkin> | ACTION pokes thoughtpolice |
| 05:35:15 | <shachaf> | mushtar: "running"? |
| 05:35:20 | <Cale> | But I don't think that's what people are talking about here :) |
| 05:35:34 | <mushtar> | shachaf: yes, running the monad? |
| 05:35:39 | <shachaf> | What does that mean? |
| 05:35:45 | <mushtar> | shachaf: monads are computations right? |
| 05:35:47 | <Cale> | (That is, the contents of the IO monad are all the types IO t for each t :) |
| 05:35:53 | <pumpkin> | mushtar: they can be thought of them |
| 05:35:56 | <pumpkin> | *as |
| 05:36:36 | <Cale> | monads are type constructors which construct types whose values can often be thought of as computations |
| 05:36:40 | <pumpkin> | ACTION is trying to get people excited about his breakthrough with ghc, but no one who cares is around :( |
| 05:36:41 | <mushtar> | > join (Nothing) |
| 05:36:52 | <Cale> | pumpkin: breakthrough? |
| 05:37:01 | <pumpkin> | I got ghc working on x86_64 on mac os :) |
| 05:37:03 | <mushtar> | > join (Nothing) |
| 05:37:04 | <lambdabot> | Nothing |
| 05:37:09 | <mushtar> | so why does that work? |
| 05:37:22 | <Cale> | mushtar: Because Nothing :: Maybe (Maybe t) |
| 05:37:29 | <dibblego> | > Nothing :: Maybe (Maybe Int) |
| 05:37:31 | <lambdabot> | Nothing |
| 05:37:41 | <mushtar> | oh.. interesting |
| 05:37:57 | <pumpkin> | just like [] could be an empty list of Ints, Bools, or anything else |
| 05:38:48 | <mushtar> | so can you extract the value out of a monad, in general? |
| 05:38:55 | <pumpkin> | no |
| 05:39:02 | <pumpkin> | only in certain particular cases |
| 05:39:07 | <shachaf> | mushtar: Monads don't have values. |
| 05:39:17 | <mushtar> | shachaf: according to Cale they do |
| 05:39:31 | <mushtar> | <Cale> monads are type constructors which construct types whose values can |
| 05:39:31 | <mushtar> | often be thought of as computations |
| 05:39:37 | <shachaf> | Yes. |
| 05:39:47 | <mushtar> | So why don't Monads have values? |
| 05:39:52 | <pumpkin> | they may have many of them |
| 05:39:54 | <shachaf> | A value :: (Monad m) => m a can't be turned into a value :: a. |
| 05:40:07 | <pumpkin> | mushtar: or none of them |
| 05:40:12 | <shachaf> | Because, for instance, there may be no value :: a. |
| 05:40:16 | <shachaf> | (As in Nothing and [].) |
| 05:40:31 | <mushtar> | But a value :: (Monad (Monad m)) => m (m a) can be turned into a value :: m a? |
| 05:40:31 | <shachaf> | Or it may take extra arguments to produce it, as in Reader and State. |
| 05:40:39 | <pumpkin> | mushtar: yup :) |
| 05:40:44 | <shachaf> | Not (Monad (Monad m)). |
| 05:40:48 | <shachaf> | @ty join |
| 05:40:49 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => m (m a) -> m a |
| 05:40:54 | <mushtar> | Oh yes |
| 05:41:02 | <shachaf> | And yes, it can. |
| 05:41:13 | <pumpkin> | that's one of the defining characteristics of a monad |
| 05:41:13 | <Apocalisp> | (Comonad m) => m a -> a |
| 05:41:30 | <mushtar> | pumpkin: why is that? |
| 05:41:46 | <pumpkin> | mushtar: think of a list, for example |
| 05:41:52 | <shachaf> | Apocalisp: I don't think that would be very helpful at this point. :-) |
| 05:41:55 | <Apocalisp> | heh |
| 05:42:00 | <pumpkin> | you can flatten nested lists down to a single list, but you can't flatten it past that |
| 05:42:12 | <mushtar> | so it's turtles all the way down? |
| 05:42:17 | <shachaf> | mushtar: I think the join/fmap/return definition of a monad is nicer than >>=/return. |
| 05:42:39 | <mushtar> | shachaf: why is that? |
| 05:42:41 | <Apocalisp> | shachaf: Easier to understand. |
| 05:42:43 | <pumpkin> | mushtar: asking for a function Monad m => m a -> a would be like asking for a meaningful function [a] -> a |
| 05:42:45 | <Cale> | pumpkin: what? |
| 05:42:52 | <pumpkin> | lol |
| 05:43:02 | <shachaf> | How about: |
| 05:43:03 | <pumpkin> | ACTION shuts up |
| 05:43:14 | <Cale> | pumpkin: I suppose a monad could have no elements, but the list monad always has lots. |
| 05:43:14 | <mushtar> | ok this makes sense |
| 05:43:21 | <jbhatta> | (pumpkin: do you mean a NATURAL function [a]->a ?) |
| 05:43:24 | <Cale> | For every type t, [t] is inhabited |
| 05:43:32 | <shachaf> | data Null a = Null; instance Monad Null where return _ = Null; Null >>= _ = Null |
| 05:43:35 | <Cale> | So, that's not an empty monad by any measure |
| 05:43:42 | <shachaf> | That's a valid monad where a is *never* used. |
| 05:43:48 | <pumpkin> | I'm just trying to give the intuition of why it doesn't make sense to ask for m a -> a |
| 05:43:50 | <shachaf> | It doesn't even exist. |
| 05:44:06 | <Cale> | Actually, that's a lie, there's no empty monad |
| 05:44:17 | <pumpkin> | me? |
| 05:44:30 | <pumpkin> | oh |
| 05:44:31 | <Apocalisp> | mushtar: You already know what a higher-order function is, right? |
| 05:44:35 | <Cale> | Because whenever x :: t, we have return x has to be an element of m t |
| 05:44:36 | <mushtar> | Apocalisp: yes |
| 05:44:50 | <shachaf> | Cale: Sure, but a value of type t never exists. |
| 05:44:51 | <Apocalisp> | mushtar: And you know what a functor is, yes? (fmap, map) |
| 05:44:56 | <shachaf> | Just :: m t. |
| 05:44:57 | <mushtar> | Apocalisp: no |
| 05:45:18 | <Cale> | shachaf: I mean, you can pick any type you want which has values, and it shows that the monad has members |
| 05:45:19 | <shachaf> | mushtar: A functor is something that has an equivalent of map. :-) |
| 05:45:21 | <shachaf> | @ty fmap |
| 05:45:22 | <lambdabot> | forall a b (f :: * -> *). (Functor f) => (a -> b) -> f a -> f b |
| 05:45:30 | <Apocalisp> | mushtar: OK. A functor is any type t for which there exists a function (a -> b) -> t a -> t b. |
| 05:45:38 | <Cale> | shachaf: Just :: t -> m t |
| 05:45:50 | <Apocalisp> | @type map |
| 05:45:51 | <lambdabot> | forall a b. (a -> b) -> [a] -> [b] |
| 05:46:01 | <mushtar> | okay i see |
| 05:46:01 | <Apocalisp> | see, List is a functor |
| 05:46:35 | <Cale> | The smallest monad you can have is data Trivial a = T |
| 05:46:36 | <Apocalisp> | A functor also has to satisfy some obvious laws, but we'll let that sit. |
| 05:46:54 | <Apocalisp> | mushtar: A monad is just a functor with an additional method: join. |
| 05:46:56 | <Apocalisp> | @type join |
| 05:46:57 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => m (m a) -> m a |
| 05:47:00 | <Cale> | With return x = T, and T >>= f = T |
| 05:47:05 | <Saizan> | Apocalisp: and return |
| 05:47:12 | <Cale> | But it is inhabited. |
| 05:47:13 | <Apocalisp> | oh snap, and return |
| 05:47:17 | <Apocalisp> | @type return |
| 05:47:18 | <lambdabot> | forall a (m :: * -> *). (Monad m) => a -> m a |
| 05:47:22 | <mushtar> | Should it be trivial to see that the two definitions of monads are equivalent? |
| 05:47:28 | <mushtar> | Because I don't see it. |
| 05:47:37 | <Cale> | mushtar: It's not hard, but not trivial either |
| 05:47:42 | <shachaf> | Apocalisp: You need return too. |
| 05:47:52 | <Apocalisp> | yep, got it |
| 05:47:52 | <shachaf> | Er, sorry. |
| 05:47:56 | <Apocalisp> | :) |
| 05:48:13 | <Cale> | mushtar: If you have >>= you can get join by using join x = x >>= id |
| 05:48:16 | <shachaf> | ACTION learns not to switch away from the IRC window for too long without reading back... |
| 05:48:32 | <mushtar> | i see |
| 05:48:47 | <Cale> | and if you have join, you can get >>= by using x >>= f = join (fmap f x) |
| 05:49:37 | <Cale> | Now, monads are required to satisfy a few simple laws in addition, and the laws can be stated in terms of fmap/return/join or in terms of return/>>= |
| 05:50:17 | <Apocalisp> | > tails [1,2,3] |
| 05:50:18 | <lambdabot> | [[1,2,3],[2,3],[3],[]] |
| 05:50:24 | <Apocalisp> | > join (tails [1,2,3]) |
| 05:50:25 | <lambdabot> | [1,2,3,2,3,3] |
| 05:51:04 | <Cale> | If you're interested, I can go over what they are. |
| 05:51:14 | <jbhatta> | ACTION is interested, so please do it anyway |
| 05:51:18 | <mushtar> | Cale: i've read about them, stuff like associativity, etc? |
| 05:51:24 | <Cale> | yeah |
| 05:51:42 | <Cale> | Actually, my favourite way to write the laws uses neither of these presentations |
| 05:51:58 | <Cale> | The laws are much prettier when written in terms of return and <=< |
| 05:52:04 | <Cale> | :t (<=<) |
| 05:52:05 | <lambdabot> | forall b (m :: * -> *) c a. (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c |
| 05:52:14 | <pumpkin> | ooh |
| 05:52:19 | <Cale> | It's defined by: |
| 05:52:24 | <mushtar> | that's a handful |
| 05:52:26 | <Apocalisp> | kleisli composition? |
| 05:52:34 | <dmwit> | mushtar: Compare the type of (.): |
| 05:52:36 | <dmwit> | :t (.) |
| 05:52:37 | <lambdabot> | forall b c a. (b -> c) -> (a -> b) -> a -> c |
| 05:52:55 | <Cale> | Yeah, it's like composition, but instead of functions (a -> b), you have (a -> m b) |
| 05:53:23 | <Cale> | (g <=< f) x = do v <- f x; g v |
| 05:53:32 | <Cale> | or: |
| 05:53:42 | <Cale> | (g <=< f) x = f x >>= \v -> g v |
| 05:53:47 | <Cale> | which is |
| 05:53:52 | <Cale> | (g <=< f) x = f x >>= g |
| 05:54:17 | <Cale> | So that's how it goes in terms fo >>= |
| 05:54:18 | <Cale> | of* |
| 05:54:30 | <Cale> | Let me state the laws using it |
| 05:54:35 | <cnwdup> | > "hello" :: ByteString |
| 05:54:36 | <lambdabot> | Not in scope: type constructor or class `ByteString' |
| 05:54:39 | <Cale> | 1) return <=< f = f |
| 05:54:40 | <cnwdup> | > "hello" :: B.ByteString |
| 05:54:41 | <lambdabot> | Failed to load interface for `B': |
| 05:54:41 | <lambdabot> | Use -v to see a list of the fi... |
| 05:54:50 | <Cale> | 2) f <=< return = f |
| 05:54:59 | <cnwdup> | However, is this possible with XOverloadedStrings? |
| 05:55:05 | <Cale> | 3) (f <=< g) <=< h = f <=< (g <=< h) |
| 05:55:07 | <dmwit> | cnwdup: It should be, yes. |
| 05:55:21 | <Cale> | So they say that return is an identity for <=< |
| 05:55:25 | <Cale> | and that <=< is associative |
| 05:55:33 | <jbhatta> | cale: that composition rule certainly makes the identities prettier |
| 05:55:55 | <dmwit> | cnwdup: I'm not sure where to find the appropriate instances, though. |
| 05:55:56 | <mushtar> | that's nicer than the way i learned it |
| 05:56:20 | <jbhatta> | Cale: can you show that it's equivalent to the usual identities using >>= et al? |
| 05:56:29 | <jbhatta> | is it a simple matter of expanding <=<? |
| 05:56:31 | <Cale> | Yes, by expanding out the definition of <=< |
| 05:56:39 | <jbhatta> | okay |
| 05:56:40 | <Cale> | and applying it to an argument |
| 05:56:46 | <shachaf> | dmwit: Data.ByteString.Lazy.Char8 has one, at least. |
| 05:57:32 | <Cale> | But this form of the laws is a little bit far away perhaps from the way that we usually program. |
| 05:57:40 | <Cale> | Maybe... |
| 05:58:12 | <Saizan> | unless you program in pointsfree style :) |
| 05:58:22 | <dmwit> | It's not *so* far. |
| 05:58:35 | <dmwit> | I use (>=>) fairly often. |
| 05:58:38 | <Cale> | In the computational viewpoint, it should still be clear that the first two laws essentially say that return x gives a computation which has no effect but produces x as its result |
| 05:59:12 | <Cale> | (What do we mean by no effect? Well, the laws make it formal.) |
| 05:59:36 | <Cale> | The third law is extremely important for composability of programs. |
| 06:00:11 | <Cale> | It essentially is what lets us take a chunk out of the middle of a do-block, decide that it's useful and make it into a new definition, and then call it, without changing the meaning of the program. |
| 06:00:36 | <Cale> | (or, inline a definition into the middle of a do-block) |
| 06:02:01 | <Cale> | It's partly because we can move the brackets around that do-blocks make any sense in the first place -- things are combined in a long sequence, but the order in which the subsequences are paired up to make it doesn't matter. |
| 06:03:50 | <Cale> | So, the third laws in essence just formalises our expectation that it doesn't matter if you: |
| 06:03:53 | <Cale> | put on your socks then (put on your shoes then tie the laces) |
| 06:03:54 | <Cale> | or |
| 06:04:00 | <Cale> | (put on your socks then put on your shoes) then tie the laces |
| 06:04:09 | <Cale> | law* |
| 06:04:37 | <Cale> | Is that cool? |
| 06:05:42 | <mushtar> | yes it makes sense |
| 06:05:50 | <pumpkin> | oh, is that what makes it a monoid in the category of endofunctors? I've heard that mentioned before, but didn't make the connection |
| 06:06:16 | <Cale> | Well... actually, the return/join version is closer to that |
| 06:06:25 | <Cale> | This is what makes the Kleisli category a category. |
| 06:06:45 | <Cale> | (of course, they're all closely related) |
| 06:07:08 | <pumpkin> | ah, cool |
| 06:07:14 | <dibblego> | I'm going to give a talk to a bunch of Java guys -- I don't want it o be boring (i.e. this is the syntax for list) and I don't want to lose the audience, so I figure monadic parsers (without saying the m word) -- comments? |
| 06:07:41 | <Cale> | For the monoid object in the category of endofunctors bit, you need to know that the sense of the word 'monoid' has been generalised quite a bit. |
| 06:07:57 | <Ycros> | dibblego: yeah, that would be pretty cool |
| 06:08:55 | <pumpkin> | Cale: oh, I just saw what you said earlier as making >=> an associative operator, with return as the identity element |
| 06:09:03 | <Cale> | pumpkin: yeah |
| 06:09:35 | <Cale> | pumpkin: but the type of >=> isn't quite right for it to make a monoid... however, it makes the next closest thing |
| 06:09:41 | <Cale> | A category |
| 06:10:39 | <pumpkin> | what is missing about >=>'s type to make it a regular monoid? I can see how it would be a category though |
| 06:10:51 | <Cale> | Well, you can't compose any two arrows. |
| 06:11:01 | <pumpkin> | oh |
| 06:11:03 | <Cale> | So it's not a set sort of monoid |
| 06:11:06 | <pumpkin> | I see |
| 06:11:20 | <pumpkin> | so it's a "monoid with incompatible elements" |
| 06:11:22 | <pumpkin> | :P |
| 06:11:30 | <Cale> | yeah, which we also call a category :) |
| 06:11:34 | <pumpkin> | yeah :) I see now |
| 06:11:37 | <pumpkin> | cool |
| 06:11:50 | <Apocalisp> | The existence of mzero and mplus make monads moinoidal objects, right? |
| 06:12:05 | <pumpkin> | ACTION eats some gummy bears to celebrate |
| 06:12:08 | <Cale> | Apocalisp: hmm... |
| 06:12:44 | <Cale> | Apocalisp: Maybe in some particular sense, but not in any of the senses we've yet discussed |
| 06:13:15 | <Cale> | In order to understand the concept of a monoid object, first you need to know what a monoidal category is (it's the sort of category in which we can define monoid objects) |
| 06:13:18 | <Apocalisp> | i.e. for all monads m and all a, (m a) is a monoid |
| 06:13:35 | <pumpkin> | well, MonadPlus? |
| 06:13:50 | <Cale> | For all monadpluses ;) |
| 06:14:01 | <Apocalisp> | heh |
| 06:14:18 | <Cale> | It's true, but I'm not sure if I see how that makes m into a monoid object in any category... |
| 06:14:30 | <Apocalisp> | What's a familiar monad that doesn't satisfy MonadPlus? |
| 06:14:39 | <Cale> | State s |
| 06:14:47 | <Apocalisp> | ah, ok |
| 06:14:52 | <Cale> | Or for that matter (->) e |
| 06:15:07 | <Cale> | Let me explain the way that m is a monoid object in the category of endofunctors |
| 06:15:09 | <Apocalisp> | -> e does only if e is a monoid |
| 06:15:15 | <pumpkin> | yay |
| 06:15:24 | <pumpkin> | Apocalisp: yeah, but we can't write -> e can we? |
| 06:15:25 | <Cale> | Apocalisp: other way around ;) |
| 06:15:37 | <Apocalisp> | forgot parens |
| 06:16:01 | <pumpkin> | I thought it was true only if you left out parens |
| 06:16:05 | <pumpkin> | but you can't write it without parens |
| 06:16:10 | <pumpkin> | :P |
| 06:16:14 | <Cale> | A monoidal category is a category C which has a bifunctor that I'll call * : C x C -> C |
| 06:16:15 | <Apocalisp> | (e ->) then |
| 06:16:33 | <Cale> | That means, it's a functor in each parameter. |
| 06:16:50 | <Cale> | and an object I of C |
| 06:17:18 | <Cale> | Together with some natural isomorphisms (A * B) * C ~= A * (B * C) |
| 06:17:28 | <Cale> | and I * A ~= A and A * I ~= A |
| 06:17:39 | <Cale> | The most familiar example is (,) |
| 06:17:41 | <Cale> | and () |
| 06:17:48 | <Cale> | (ignoring strictness for now) |
| 06:18:11 | <Cale> | Because (a,(b,c)) ~= ((a,b),c) |
| 06:18:12 | <pumpkin> | (,) being the bifunctor? |
| 06:18:23 | <Cale> | and ((),a) ~= a ~= (a,()) |
| 06:18:25 | <Cale> | yeah |
| 06:18:59 | <Cale> | But the category of endofunctors with natural maps between them is a monoidal category in a different way |
| 06:19:18 | <pumpkin> | what do you mean by ~= ? |
| 06:19:22 | <Cale> | isomorphic to |
| 06:19:26 | <pumpkin> | oh ok :) |
| 06:19:35 | <Cale> | (naturally isomorphic to, if you want to be more technical) |
| 06:19:56 | <pumpkin> | not sure what the naturally qualification adds to it :) I haven't read that far in awodey yet |
| 06:20:13 | <pumpkin> | but the plain ol' isomoprhic makes sense |
| 06:20:22 | <Cale> | It basically just means that the isomorphism is supposed to "do the same thing" regardless of what A,B,C are |
| 06:20:37 | <Cale> | In Haskell, we'd expect it to be realised as a polymorphic function |
| 06:20:47 | <Cale> | But actually polymorphism is a little stronger |
| 06:20:52 | <pumpkin> | ok |
| 06:21:08 | <Cale> | In the category [C,C] of endofunctors on C, we take the * to be composition of functors(!) and the I to be the identity functor. |
| 06:21:38 | <pumpkin> | what's the [C,C] notation? |
| 06:21:48 | <Cale> | Functors from one category to another |
| 06:21:52 | <pumpkin> | oh ok :) |
| 06:21:58 | <Cale> | C^C would work too :) |
| 06:22:00 | <Cale> | Or C -> C |
| 06:22:04 | <pumpkin> | cool |
| 06:22:10 | <Cale> | (though that's more haskelly) |
| 06:22:15 | <Cale> | Since composition is associative, we get that A . (B . C) is isomorphic to (A . B) . C |
| 06:22:37 | <Cale> | (more than that, they're equal) |
| 06:22:46 | <Cale> | and since the identity functor is an identity, A . id = A = id . A |
| 06:23:31 | <Cale> | Oh, actually there are some annoyingly technical conditions which the isomorphisms are supposed to satisfy... I'm not going to bother with that |
| 06:23:52 | <Cale> | anyway! |
| 06:23:56 | <pumpkin> | :) |
| 06:24:42 | <Cale> | If we have a monoidal category, a monoid object in it is an object M together with two arrows: mu: M * M -> M |
| 06:24:48 | <Cale> | and eta: I -> M |
| 06:25:01 | <Cale> | and they have to satisfy a few laws |
| 06:26:30 | <Cale> | But you can already start to see how in the category of endofunctors, this is starting to look like a monad |
| 06:27:07 | <Cale> | In Haskell, we might realise mu as a function of type M (M a) -> M a |
| 06:27:09 | <pumpkin> | that's an eye -> M |
| 06:27:12 | <pumpkin> | not ell, right? |
| 06:27:15 | <Cale> | yeah |
| 06:27:19 | <pumpkin> | yeah :) |
| 06:27:25 | <Cale> | and eta as a -> M a |
| 06:27:25 | <pumpkin> | and eta is return |
| 06:27:44 | <pumpkin> | that's neat |
| 06:28:10 | <Cale> | The laws they have to satisfy are analogous to the laws for a monoid in Set |
| 06:28:55 | <Cale> | If we start from M * M * M |
| 06:29:29 | <Cale> | We can either look at that as M * (M * M) and apply mu on the right to get to M * M and then apply mu again to get to M |
| 06:30:14 | <Cale> | Or, by the required isomorphism, we can look at it as (M * M) * M and apply mu on the left (since * is a bifunctor), and get to M * M, and then apply mu again to get to M |
| 06:30:35 | <Cale> | and the associativity law says these compositions have to be equal |
| 06:31:20 | <Cale> | That is, in Haskelly notation, join . fmap join = join . join |
| 06:32:22 | <Cale> | Follow that much? |
| 06:32:40 | <Cale> | It may help to draw a diagram or look at the one on http://en.wikipedia.org/wiki/Monoid_object |
| 06:33:40 | <Cale> | One of the unit laws is that if we start from I * M and apply eta on the I to get to M * M and then mu to get to M, the result is the same as the isomorphism I * M -> M gives us |
| 06:34:07 | <Cale> | Of course, the isomorphism is actually an equality in the endofunctor case |
| 06:35:01 | <Cale> | and so this says join . return = id |
| 06:35:43 | <Cale> | Or, starting from M * I, we can apply eta on the I to get to M * M and then mu to get to M, and that should be the same as the isomorphism M * I -> M gives us |
| 06:36:14 | <pumpkin> | yup :) |
| 06:36:15 | <Cale> | and translated into the endofunctor case and then to Haskell, that gives us that join . fmap return = id |
| 06:36:36 | <pumpkin> | I think I actually followed all of that |
| 06:36:43 | <Cale> | Great! |
| 06:38:10 | <Cale> | To get the normal notion of monoids, you take the category of sets, and * becomes Cartesian product, and I becomes any one-element set. |
| 06:38:28 | <Cale> | mu: M x M -> M |
| 06:38:35 | <Cale> | is the multiplication in the monoid (mappend) |
| 06:38:53 | <Cale> | and eta: 1 -> M is a function which picks out the identity element (const mempty) |
| 06:40:01 | <Cale> | Which goes to show that if you abstract any two concepts far enough, they will eventually look the same ;) |
| 06:40:09 | <pumpkin> | hah |
| 06:43:18 | <Cale> | Hmm... |
| 06:43:41 | <pumpkin> | ? |
| 06:43:56 | <Cale> | Just wondering now how to go most efficiently from the endofunctor presentation to the Kleisli composition presentation |
| 06:43:56 | <cnwdup> | How can I catch signals like ^C (SIGTERM?) in Haskell? |
| 06:44:09 | <pumpkin> | isn't that SIGINT? |
| 06:44:16 | <cnwdup> | Probably. (: |
| 06:44:32 | <dmwit> | Have you checked in the System hierarchy? |
| 06:44:46 | <Cale> | There's a posix library which has stuff related to signals as I recall... |
| 06:44:58 | <dmwit> | http://www.haskell.org/ghc/docs/latest/html/libraries/unix/System-Posix-Signals.html |
| 06:44:58 | <cnwdup> | Cale, dmwit, thanks. Will see if I can find it. |
| 06:45:36 | <Cale> | installHandler :: Signal -> Handler -> Maybe SignalSet -> IO Handler |
| 06:45:54 | <Cale> | data Handler |
| 06:45:55 | <Cale> | = Default |
| 06:45:55 | <Cale> | | Ignore |
| 06:45:55 | <Cale> | | Catch (IO ()) |
| 06:45:55 | <Cale> | | CatchOnce (IO ()) |
| 06:47:55 | <Cale> | so... installHandler keyboardSignal (Catch handleCtrlC) Nothing |
| 06:48:25 | <cnwdup> | Cale, thanks |
| 06:49:02 | <Cale> | It probably isn't the least bit windows compatible |
| 06:49:23 | <cnwdup> | That's okay for me. |
| 06:49:54 | <dmwit> | Windows is POSIX-compliant, I thought. |
| 06:50:12 | <Cale> | "The package is not supported under Windows (except under Cygwin)." |
| 06:50:25 | <p_l> | dmwit: it is, but you need to install additional package (SUA) |
| 06:51:17 | <p_l> | and GHC probably doesn't use that :) |
| 06:51:51 | <dmwit> | aha |
| 06:52:06 | <magical_pony> | are there any major differences between ghc(i) and hugs? |
| 06:52:15 | <magical_pony> | why would one use hugs over ghc? |
| 06:52:20 | <pumpkin> | you wouldn't |
| 06:52:22 | <Cale> | ghc is a compiler |
| 06:52:32 | <Cale> | and ghci a bytecode interpreter |
| 06:52:40 | <Cale> | hugs is an interpreter |
| 06:52:40 | <magical_pony> | yes... then why does hugs exist? |
| 06:52:43 | <magical_pony> | ooooh |
| 06:53:08 | <Cale> | Because people were working on it since the very earliest days of Haskell. |
| 06:53:23 | <Lemmih> | It's also more portable, I think. |
| 06:53:29 | <magical_pony> | understood. is there a standard implementation of the haskell language? |
| 06:53:40 | <magical_pony> | i suppose i can consult haskell.org |
| 06:53:43 | <Cale> | magical_pony: I would normally just recommend GHC |
| 06:53:49 | <dmwit> | GHC is the most widely-used implementation. |
| 06:54:09 | <dmwit> | If you have problems with other implementations, people will likely say, "use GHC" rather than support the other implementation. ;-) |
| 06:54:21 | <magical_pony> | alright, thanks. |
| 06:54:33 | <Cale> | Hugs is the only other maintained implementation which isn't in a somewhat experimental state right now, I think. |
| 06:54:51 | <Cale> | And GHC produces much faster code and has more cool features. |
| 06:55:01 | <magical_pony> | so there are differences! |
| 06:55:06 | <Cale> | (like a profiler, code coverage tools, and so on) |
| 06:55:14 | <Cale> | and language extensions, yes |
| 06:55:14 | <magical_pony> | oh, development tools, i see. |
| 06:55:23 | <pumpkin> | onoes, xzibit got into the GHC GMP build -D__GMP_WITHIN_GMP |
| 06:55:33 | <Cale> | ahahhaa |
| 06:55:50 | <magical_pony> | sure is b in here |
| 06:56:31 | <p_l> | <insert mandatory "yo, dawg" joke here> |
| 06:58:26 | <pumpkin> | :) |
| 07:05:14 | <Adamant> | ghc is effectively the reference implementation. some other compilers have more aggressive designs that may eventually pass ghc in compiled code speed, but they're still effectively alpha, beta, or just plain "experimental". unless you're using Haskell for teaching purposes (where Hugs is good), just use ghc, everyone else does :P |
| 07:07:01 | <Cale> | BONUS's twitter is bewildering |
| 07:07:06 | <pumpkin> | sure is :) |
| 07:07:09 | <pumpkin> | I love his background |
| 07:07:46 | <Cale> | http://s3.amazonaws.com/twitter_production/profile_background_images/2932631/81ced870c37efd64bf957aff6cf91437ddb588c3.gif |
| 07:08:04 | <pumpkin> | it's pretty epic |
| 07:08:17 | <Cale> | I wonder if he made it himself or found it somewhere |
| 07:08:53 | <erikc`> | reminds me of http://upload.wikimedia.org/wikipedia/en/1/17/Last_unicorn.jpg |
| 07:09:02 | <erikc`> | that red bull scared me so much as a child |
| 07:09:49 | <Cale> | "imagine a giant snail playing the imperial march on a tuba really slowly" "the giant snail puts down its tuba and sings Pagliacci in a tenor voice. It's ok but you can't believe you payed $300 for this crap." |
| 07:12:42 | <pumpkin> | @tell thoughtpolice I have a (very hacky) 64-bit ghc HEAD running on mac os! |
| 07:12:42 | <lambdabot> | Consider it noted. |
| 07:13:32 | <Gracenotes> | kip kip |
| 07:13:45 | <pumpkin> | kip kip? |
| 07:13:51 | <magical_pony> | mud |
| 07:13:53 | <Cale> | mudkips? |
| 07:14:25 | <Gracenotes> | kip |
| 07:14:29 | <magical_pony> | mud |
| 07:14:41 | <Gracenotes> | kip |
| 07:14:44 | <magical_pony> | mud |
| 07:14:48 | <Gracenotes> | kip |
| 07:14:52 | <magical_pony> | mud |
| 07:14:56 | <Gracenotes> | slooooooooowpoke |
| 07:15:01 | <magical_pony> | D: |
| 07:15:30 | <dmwit> | Did it suddenly get rather random in here, or is it just me? |
| 07:15:42 | <Cale> | It just got /b/ in here. |
| 07:15:52 | <dmwit> | /b/ stands for random ;-) |
| 07:15:54 | <magical_pony> | lol |
| 07:16:24 | <Raevel> | wow |
| 07:16:25 | <Gracenotes> | they are the favored pokemon of the internet, regardless of what thrust them into that light |
| 07:16:50 | <Raevel> | i choose you Gracenotes |
| 07:17:30 | <p_l> | magical_pony, Gracenotes: Low-endian mudkips? |
| 07:17:32 | <Cale> | There needs to be a pokemon called C-C-C-COMBO BREAKER |
| 07:17:46 | <p_l> | *Little-Endian |
| 07:18:18 | <magical_pony> | i should hope so, i have no idea what a big-endian mudkip would look like |
| 07:18:58 | <p_l> | normally, "mudkip". However, here I had seen "Gracenotes: kip" "magical_pony: mud" :P |
| 07:19:18 | <magical_pony> | oh, i get your joke now. |
| 07:19:20 | <Raevel> | is there any difference in how universal quantifiers are treated with or without glasgow-exts in ghc (except that you get the syntactical forall)? |
| 07:19:29 | <Gracenotes> | although, perhaps if you let them hold a big-endian rock in battle.. |
| 07:20:06 | <Cale> | Raevel: without that syntax, the implicit foralls are always considered to be at the very start of the type signature |
| 07:20:20 | <dmwit> | Raevel: I'm not sure exactly which extensions glasgow-exts includes, but there are, for example, rank-n types and scoped type variables. |
| 07:20:28 | <Cale> | Raevel: So, I suppose, you get other sorts of polymorphism |
| 07:20:58 | <Cale> | Oh, yeah, the scoped type variables thing is another big difference |
| 07:21:20 | <opqdonut> | does glasgow-exts include scoped typevars? i'm sure it doesn't have rankN |
| 07:21:42 | <Cale> | I don't know, I haven't used it in many versions |
| 07:21:57 | <Raevel> | ah okay |
| 07:22:06 | <Cale> | If you explicitly quantify your type variables with forall, then the variables scope over the function/value's definition |
| 07:22:23 | <Cale> | and can be used to refer to the type which the function was applied at |
| 07:23:18 | <opqdonut> | there doesn't seem to be a list of the extensions -fglasgow-exts enables anywhere |
| 07:24:00 | <dmwit> | I'm sure it's solidly deprecated by now anyway. |
| 07:24:12 | <Raevel> | i was also wondering why an expression like (f -> (f 1, f ())) id doesn't type check, why isn't forall assumed for f? |
| 07:24:13 | <Cale> | I'm almost certain I've seen one in the GHC documentation... |
| 07:24:27 | <Cale> | Raevel: kind error? |
| 07:24:30 | <Cale> | er |
| 07:24:37 | <Cale> | Wait... that's an expression? |
| 07:24:43 | <dmwit> | Raevel: That's rank-2 polymorphism. |
| 07:24:51 | <dmwit> | Cale: He meant (\f -> (f 1, f ())) id |
| 07:24:53 | <Cale> | Oh, it's meant to be a lambda |
| 07:24:54 | <Cale> | yeah |
| 07:25:03 | <Raevel> | oh, right, sorry |
| 07:25:14 | <Cale> | Yeah, that required the inferred type for f to be polymorphic |
| 07:25:39 | <Cale> | GHC never infers polytypes for function parameters |
| 07:25:54 | <opqdonut> | http://darcs.haskell.org/ghc/compiler/main/DynFlags.hs |
| 07:25:57 | <opqdonut> | search for glasgow |
| 07:26:12 | <Raevel> | neither does ML iirc, is there a reason for it? |
| 07:26:28 | <opqdonut> | ah, glasgowexts has Opt_ExistentialQuantification |
| 07:26:35 | <ChilliX> | pumpkin: Great! |
| 07:26:35 | <lambdabot> | ChilliX: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 07:26:49 | <pumpkin> | ChilliX: it's still a mess though :) |
| 07:26:51 | <opqdonut> | Raevel: those are generally non-inferrable AIUI |
| 07:27:13 | <Saizan> | Raevel: yes, type inference is undecidable for arbitrary-rank polymorphism |
| 07:27:25 | <Cale> | However, you can, with rank-2 polymorphism give that function an appropriate type, like: |
| 07:27:29 | <ChilliX> | pumpkin: Why a mess? Did you have to change much? |
| 07:27:40 | <opqdonut> | rank-2 is a nice compromise between inferrability and power |
| 07:28:01 | <pumpkin> | ChilliX: well, the way I did it, I forgot to tell the linker to link x86_64, so I had to link all the things by hand because I didn't want to wait for the whole thing to recompile |
| 07:28:10 | <pumpkin> | ChilliX: mostly had to change things in the Driver |
| 07:28:14 | <Cale> | foo :: forall a. (a -> a) -> (Integer, ()) |
| 07:28:15 | <Cale> | er |
| 07:28:23 | <Cale> | foo :: (forall a. a -> a) -> (Integer, ()) |
| 07:28:34 | <Cale> | foo f = (f 1, f ()) |
| 07:29:22 | <Raevel> | ah, i hade the impression that it was restricted for some reason (no idea where i got that idea from) |
| 07:30:09 | <Cale> | Raevel: oh, you mean artificially? |
| 07:30:35 | <jkff> | Note to self: By taking a lambda term, translating it into a point-free form (to combinators, for example), writing down the free theorem of every (now closed) subterm and solving the resulting system of type equivalences, we can obtain a nice free theorem for the whole term that is stronger than simply the free theorem of its type. |
| 07:30:53 | <Raevel> | i'm not sure what you mean by artificially" |
| 07:30:55 | <pumpkin> | ChilliX: the difficult mostly comes from mac os defaulting to building i386 instead of x86_64 (and I don't know any easy way of temporarily changing the default) |
| 07:31:16 | <Cale> | Raevel: Er, I suppose I don't know what you meant by 'restricted'. |
| 07:31:22 | <Raevel> | oh, terrible lag |
| 07:31:30 | <Raevel> | :-D |
| 07:33:09 | <hatds> | god |
| 07:33:14 | <pumpkin> | ? |
| 07:33:29 | <jkff> | [I wonder whether someone has already written a paper or a blogpost about that. If not, I will :) /me tries it out on "foldr (insertWhere (<)) []"] |
| 07:33:34 | <hatds> | ghc just gave me 50 error dialogs in a row with only "OK" to go through them |
| 07:33:42 | <Raevel> | bah, i have to get off this trait now. thanks for the help everyone, i may pop in later and try to explain myself :-) |
| 07:33:48 | <Raevel> | s/trait/train |
| 07:33:57 | <Raevel> | bye! |
| 07:34:13 | <jkff> | @pl \lt -> foldr (insert lt) [] |
| 07:34:13 | <lambdabot> | flip foldr [] . insert |
| 07:34:15 | <hatds> | and it wasn't some horrible crash... the problem was I specified -hc and -hb at the same time for profiling |
| 07:34:16 | <jkff> | @free flip |
| 07:34:17 | <lambdabot> | (forall x. h . k x = p (f x) . g) => h . flip k y = flip p (g y) . f |
| 07:34:21 | <jkff> | @free foldr |
| 07:34:22 | <lambdabot> | (forall x. g . h x = k (f x) . g) => g . foldr h y = foldr k (g y) . $map f |
| 07:34:29 | <jkff> | Thank you precious lambdabot |
| 07:34:40 | <hatds> | ghc was trying to display a page of helpful readme text 15 words at a time over 50 dialogs |
| 07:34:44 | <Saizan> | jkff: you apply free theorems with typeclasses involved? |
| 07:35:01 | <jkff> | Nope, dictionary passing suffices |
| 07:35:08 | <jkff> | @free (a->a->Bool)->a->[a]->[a] |
| 07:35:08 | <lambdabot> | Pattern match failure in do expression at /tmp/ghc25834_0/ghc25834_59.hspp:54:20-34 |
| 07:35:15 | <Saizan> | ah, i see |
| 07:35:37 | <jkff> | Hm. Lambdabot FAIL. Will use voigtlaender's.. |
| 07:36:03 | <dmwit> | hatds: Eh, what? GHC... dialogs? |
| 07:36:13 | <Saizan> | @free (a -> a -> Bool) -> a -> [a] -> [a] |
| 07:36:13 | <lambdabot> | Pattern match failure in do expression at /tmp/ghc25834_0/ghc25834_59.hspp:54:20-34 |
| 07:36:22 | <pumpkin> | microsoft's latest product, Visual GHC! |
| 07:36:45 | <hatds> | dmwit: well it was default error messages put into windows my program by GHC :) |
| 07:36:47 | <pumpkin> | one of the marketing people was promoted to head of microsoft research |
| 07:37:00 | <hatds> | dmwit: caused by running it with by "main.exe +RTS -hb -hc" |
| 07:37:30 | <hatds> | *windows my = my windows |
| 07:38:04 | <dmwit> | Huh, that doesn't sound like the GHC I know. I wonder why it doesn't just use stderr...? |
| 07:38:18 | <hatds> | you don't have stderr when compiling a windows program |
| 07:38:31 | <opqdonut> | @scheck \(x :: Double) -> not (x == x+1) |
| 07:38:31 | <lambdabot> | Parse error in pattern at "->" (column 16) |
| 07:38:33 | <dmwit> | um |
| 07:38:35 | <dmwit> | stdout, then ;-) |
| 07:38:45 | <hatds> | I don't think you have their either |
| 07:38:47 | <opqdonut> | @scheck \x -> not ((x :: Double) == x+1) |
| 07:38:48 | <lambdabot> | "OK, passed 500 tests." |
| 07:38:57 | <dmwit> | hatds: You *definitely* have stdout. |
| 07:38:57 | <jkff> | Holy cow, that will be one scary system for foldr insert [] |
| 07:39:45 | <dmwit> | It might not be called stdout. But you can interact with a terminal. |
| 07:40:00 | <cnwdup> | @kind (StateT s) |
| 07:40:01 | <lambdabot> | Not in scope: type variable `s' |
| 07:40:04 | <cnwdup> | @kind (StateT String) |
| 07:40:05 | <lambdabot> | (* -> *) -> * -> * |
| 07:40:45 | <hatds> | I'm trying to find where I read that |
| 07:42:04 | <cnwdup> | @kind MonadTrans |
| 07:42:05 | <lambdabot> | Class `MonadTrans' used as a type |
| 07:42:07 | <hatds> | in any case converting a stream intended for stdout into a series of dialogs is a bad idea :) |
| 07:42:51 | <dmwit> | agreed =) |
| 07:42:53 | <cnwdup> | How would I make a newtype PL s = PL { runPL :: StateT s (StateT Foo (ReaderT Bar IO)) a } instance of MonadTrans? Is this even possible? |
| 07:43:09 | <cnwdup> | I'd like to access the inner StateT monad using lift. |
| 07:43:10 | <dmwit> | deriving MonadTrnas |
| 07:43:13 | <opqdonut> | cnwdup: there's no monad argument |
| 07:43:18 | <dmwit> | with GeneralizedNewtypeDeriving |
| 07:43:21 | <cnwdup> | opqdonut, and that's the problem, right? |
| 07:43:27 | <opqdonut> | ?info MonadTrans |
| 07:43:27 | <lambdabot> | MonadTrans |
| 07:43:32 | <opqdonut> | well, yeah |
| 07:43:35 | <dmwit> | ?undo MonadTrans |
| 07:43:35 | <lambdabot> | MonadTrans |
| 07:43:42 | <dmwit> | ?info x >>= f |
| 07:43:42 | <lambdabot> | x >>= f |
| 07:43:50 | <dmwit> | ?info do { x <- f; g x } |
| 07:43:50 | <lambdabot> | f >>= \ x -> g x |
| 07:44:01 | <opqdonut> | class MonadTrans t where |
| 07:44:09 | <opqdonut> | lift :: Monad m => m a -> t m a |
| 07:44:31 | <opqdonut> | t need to have kind (* -> *) -> * -> * |
| 07:44:39 | <dmwit> | cnwdup: In any case, I guess you meant you want to make it an instance of MonadState (and MonadReader, etc.). |
| 07:44:40 | <opqdonut> | your PL has kind * -> * |
| 07:44:41 | <cnwdup> | I see. |
| 07:44:55 | <opqdonut> | (and besides, where does the a come from)? |
| 07:45:01 | <opqdonut> | so you probably meant PL s a |
| 07:45:02 | <dmwit> | cnwdup: You're going to have trouble with that, because there are two StateT monad transformers in there. |
| 07:45:12 | <opqdonut> | that too |
| 07:45:13 | <cnwdup> | dmwit, I have. But for the outer state. And I can't make it an instance of MonadState twice or can I? |
| 07:45:19 | <dmwit> | cnwdup: No, you can't. |
| 07:45:28 | <dmwit> | cnwdup: There's a fundep on MonadState that prevents it. |
| 07:45:34 | <cnwdup> | opqdonut, I meant that. Yes. |
| 07:45:47 | <dmwit> | cnwdup: Hence the "trouble." =) |
| 07:46:38 | <cnwdup> | Ah, but I can do: getFoo :: PL Foo, getFoo = PL $ lift get. (: |
| 07:46:41 | <cnwdup> | That's enough for me. |
| 07:47:35 | <mux> | damn, I didn't think of that - now that I disabled some code on some platforms with #ifdef's, the documentation of my package on hackage misses some stuff since the platform where hackage built it can't have those functions |
| 07:48:02 | <mux> | I should wire those to error calls instead I guess |
| 07:48:20 | <opqdonut> | or #ifdef deprecation pragmas or something |
| 07:48:50 | <opqdonut> | errors are too runtime, compile-time is always better |
| 07:49:01 | <mux> | it's not a matter of deprecation though |
| 07:49:38 | <opqdonut> | well that's the best solution i came up with |
| 07:50:23 | <opqdonut> | it's a shame there's no ERROR pragma like in C |
| 07:51:30 | <mux> | I guess I'll have to go with error calls |
| 07:52:31 | <mux> | otherwise if I don't define those functions I'm thinking of, I can't have some instances either, which I really want to be in the docs though |
| 07:53:16 | <PetRat> | I'm only dimly aware of how to use monad transformers. Do you have to use some variant on "lift" to put a function into an "inner monad" (not sure if that's the right term). If you "stack" more than two monad transformers, do you have to write more than one "lift"? If this is all way off never mind. |
| 07:53:33 | <opqdonut> | mux: can't you preprocess first and then run haddock? |
| 07:53:49 | <mux> | opqdonut: well this is hackage that is handling all of this |
| 07:54:08 | <opqdonut> | well a few cabal rules should do it |
| 07:54:10 | <opqdonut> | http://www.haskell.org/haddock/haddock-html-0.8/invoking.html#cpp |
| 07:54:48 | <mux> | oooh |
| 07:54:52 | <mux> | I could use __HADDOCK__ |
| 07:55:26 | <mux> | ah, that's not standard but passed via cabal |
| 07:55:40 | <mux> | that won't do it, I'm not even using CPP but actually this is a .hsc file |
| 07:55:52 | <mux> | maybe it would too though |
| 07:55:58 | <mux> | I'll hava to check |
| 07:56:14 | <PetRat> | Control.Monad.Cont "the mother of all monads" |
| 07:56:19 | <dmwit> | PetRat: You use "lift" to take actions in the inner monad into actions in the transformed monad. |
| 07:56:48 | <PetRat> | dmwit: just wondering if you've stacked more than one monad if you have to write lift twice. |
| 07:56:48 | <dmwit> | PetRat: "lift" is polymorphic in a way that means you (should) only have to use it once to lift even a deep action up out of several layers. |
| 07:56:57 | <PetRat> | oh |
| 07:57:12 | <dmwit> | PetRat: However, it doesn't hurt to write it twice. =) |
| 07:57:19 | <PetRat> | why is there a special liftIO? |
| 07:57:38 | <dmwit> | :t lift |
| 07:57:39 | <lambdabot> | forall (m :: * -> *) a (t :: (* -> *) -> * -> *). (Monad m, MonadTrans t) => m a -> t m a |
| 07:57:41 | <dmwit> | :t liftIO |
| 07:57:42 | <lambdabot> | forall a (m :: * -> *). (MonadIO m) => IO a -> m a |
| 07:57:55 | <dmwit> | Oh, you're right. I was thinking of liftIO. |
| 07:57:55 | <Saizan> | lift only works for a single transformer layer. |
| 07:58:02 | <dmwit> | You have to lift several times, but liftIO only once. |
| 07:58:09 | <hydo> | "If I had to talk to mysql with haskell, I'd use ________" |
| 07:58:27 | <opqdonut> | _______ = "bdb anyway" |
| 07:58:28 | <PetRat> | Is liftIO there for convenience or some deeper reason. |
| 07:58:38 | <PetRat> | ? |
| 07:58:42 | <Saizan> | convenience |
| 07:58:44 | <hydo> | opqdonut: heheh... ok, I'll take a look. |
| 07:59:15 | <hydo> | opqdonut: problem is that I need to have the same data present on multiple machines. |
| 07:59:36 | <hydo> | That is, assuming bdb is a gdbm, sleepycat-like thing. |
| 07:59:42 | <Ycros> | hydo: HDBC? |
| 07:59:49 | <opqdonut> | hydo: bdb is Berkeley database |
| 08:00:03 | <opqdonut> | a simple and efficient key-value db with replication etc |
| 08:00:08 | <pumpkin> | it is sleepycat :) |
| 08:00:17 | <opqdonut> | but i was just being snide actually |
| 08:00:29 | <hydo> | Ycros: ok, I'll check it out. There's a lot of them so I figured one or two were the accepted "one to use". |
| 08:00:34 | <opqdonut> | ah, yes, sleepycat |
| 08:00:36 | <hydo> | Ycros: oh, and thanks! |
| 08:02:39 | <Ycros> | anyone having trouble with the convertible package from hackage? I'm trying to build version 1.0.1 and it's complaining about duplicate instance declarations (clashing with stuff defined in time-1.1.3) |
| 08:03:10 | <hydo> | ycros: hah... I *just* got that same error. I'm assuming there's something not set as a dependency in the cabal file. |
| 08:04:12 | <Ycros> | hydo: it was all good last week or so. I but in the meantime I upgraded from ghc 6.10.1 to 6.10.3 |
| 08:04:30 | <Ycros> | I'm thinking some stuff might have gotten rolled into the time package from convertible |
| 08:04:33 | <Ycros> | dunno. |
| 08:04:56 | <cnwdup> | I have the data type Plugin s = P { getS :: s }. Is there a way to store different Plugin s in one container (list, data map, something) and let ghc figure out what type getS is depending whether it is called on Plugin Int or Plugin String? |
| 08:04:58 | <Ycros> | I have no idea where any sort of repo is for the convertible package |
| 08:05:43 | <Ycros> | hydo: I basically have a binary of my program that uses HDBC, and I can't recompile it with some changes I've been making because I can't install HDBC :-/ |
| 08:06:06 | <dmwit> | cnwdup: You can use rank-2 polymorphism to store plugins that conform to a class specification, or you can use Data.Dynamic. |
| 08:06:30 | <cnwdup> | dmwit, I'd rather not use Data.Dynamic. Where can I read up about rank-2 polymorphism? That term is new to me. (: |
| 08:06:31 | <hydo> | ycros: fixing it... or at least trying to. |
| 08:07:15 | <dmwit> | cnwdup: Whoops, I don't think I meant rank-2 polymorphism. |
| 08:07:44 | <dmwit> | Possibly existential quantification, instead. |
| 08:08:07 | <cnwdup> | I'm trying that right now. Hopefully I can get the example to work. |
| 08:08:29 | <cnwdup> | Just hoped there were something "better." I always run into problems using existential types. |
| 08:16:30 | <hydo> | Ycros: comment out lines 60 - 66 in Data/Convertible/Instances/Time.hs and it'll build. No idea if it will blow up on you, but it builds! I'm going to build the tests when I get up to, hopefully, make sure everything is ok. |
| 08:17:34 | <Ycros> | hehe |
| 08:18:01 | <hydo> | Ycros: ugh.. I don't think that was the solution. Now HDBC pukes duplicate definition errors. |
| 08:19:15 | <hydo> | Temptation to downgrade to 6.10.2 building... |
| 08:19:16 | <quicksilver> | dmwit, cnwdup : there is no need to involve classes. |
| 08:19:26 | <quicksilver> | certainly what you are describing is an existential type. |
| 08:19:27 | <Ycros> | hydo: I was going to try that actually |
| 08:19:34 | <Ycros> | (commenting stuff out) |
| 08:20:08 | <dmwit> | quicksilver: Is there a practical difference between... |
| 08:20:26 | <quicksilver> | cnwdup: of course, what you actually described doesn't sound like it makes sense, so far. |
| 08:20:45 | <dmwit> | data Plugin = forall s. Plugin { doSomething :: s -> String -> String; updateSomething :: s -> Plugin s } |
| 08:20:52 | <dmwit> | and... |
| 08:20:54 | <cnwdup> | quicksilver, what doesn't make sense? |
| 08:20:55 | <quicksilver> | cnwdup: let's suppose for a moment we could call 'getS' in a way which returned "either and Int or a String but I don't know which" |
| 08:21:02 | <quicksilver> | cnwdup: how would it be useful? |
| 08:21:15 | <quicksilver> | cnwdup: what operations can we perform on "either an Int or a String but I don't know which" ? |
| 08:21:26 | <dmwit> | quicksilver: [Plugin] vs. [forall s. DoesSomethingAndUpdatesSomething s => s]? |
| 08:21:45 | <quicksilver> | dmwit: the fact that the class-based version restricts you to one pair of functions per type 's' |
| 08:21:55 | <quicksilver> | dmwit: and always selects then based on the type. |
| 08:22:01 | <cnwdup> | I want to know what type getS returns. But it should vary depending on the first argument. If it's called on Plugin Int or Plugin String. |
| 08:22:13 | <quicksilver> | dmwit: whereas the simple higher order function version allows more flexibility. |
| 08:22:23 | <dmwit> | Well, okay. That's fair. |
| 08:22:26 | <cnwdup> | And I need a way to store Plugin s and Plugin s1 in a container where I can access them from. |
| 08:22:32 | <quicksilver> | cnwdup: think about how this will make sense in a wider context |
| 08:22:48 | <quicksilver> | cnwdup: suppose we have a list of plugins of unknown type - pp :: [SomePlugin] |
| 08:23:04 | <quicksilver> | cnwdup: if you call "getS (head pp)", what type does it return? |
| 08:23:08 | <quicksilver> | remember type checking is static. |
| 08:23:14 | <quicksilver> | how will you write code which makes sense? |
| 08:23:18 | <cnwdup> | quicksilver, I don't want the types to be unknown. |
| 08:23:34 | <quicksilver> | [aside: I'm not tryign to suggest these problems are insoluble. I'm just asking the questions which provoke the answer you need ;) ] |
| 08:23:54 | <quicksilver> | cnwdup: but what is the type of "head pp" ? |
| 08:24:31 | <cnwdup> | quicksilver, so I cannot use a list. (: |
| 08:24:42 | <dmwit> | Of course, if the list of possible types is known in advance, all of this is kind of silly, so maybe we should ask if that's the case first... |
| 08:24:53 | <cnwdup> | quicksilver, And yes, I apprechiate your provocation. |
| 08:25:35 | <cnwdup> | Suppose I have a data structure which maps the plugin name to the plugin state (s). I'd like to lookup the state using the plugin name and ghc should tell me the type. |
| 08:25:57 | <cnwdup> | But I don't know how to associate the plugin name with the plugin state and which data structure to use as storage container. |
| 08:26:30 | <cnwdup> | I would have used the plugin's name as a string and the storage container as Data.Map String (Plugin s). But then I'll run into the same problem quicksilver described with lists. ): |
| 08:26:31 | <quicksilver> | well, you sort-of can't have a structure which maps names to types |
| 08:26:36 | <quicksilver> | because types aren't values, per se. |
| 08:26:44 | <hydo> | Ycros: ok, well it builds with 598 - 593 and 598 - 603 commented out in Database/HDBC/SqlValue.hs |
| 08:26:52 | <hydo> | Ycros: no word on stability though :) |
| 08:26:54 | <quicksilver> | however, what you can do is create some values, which reify particular types. |
| 08:26:59 | <Ycros> | hydo: I'm trying to downgrade time to 1.1.2.4 for now |
| 08:27:08 | <quicksilver> | data PluginType = PTInt | PTString | {- other possibilities -} |
| 08:27:13 | <cnwdup> | quicksilver, yeah. But since the name is unique I know which name is associated with which kind of value. And I'd like ghc to know that, too. |
| 08:27:32 | <cnwdup> | quicksilver, my plugin type should be extensible from the plugin side and not from the main application side. |
| 08:27:38 | <hydo> | Ycros: probably smarter... if things don't work perfectly I'll do that tomorrow. |
| 08:28:21 | <cnwdup> | Can I somehow have a structure mapping names to states and tell ghc: names are unique, so please infer the type of the state for me? |
| 08:28:28 | <quicksilver> | If it's not extensible from the main application side, that means the main application doesn't know the total set of possible plugin types |
| 08:28:46 | <quicksilver> | if the main application doesn't know the total set of plugin types, then it can never possibly operate on them directly |
| 08:28:55 | <quicksilver> | so, it doesn't matter, and you can just use an existential. |
| 08:29:12 | <Ycros> | hydo: just worked for me |
| 08:29:23 | <cnwdup> | quicksilver, I only want the main application to provide the container. Operation is done in the plugin code. But I'd like the plugins to type check. |
| 08:30:01 | <cnwdup> | With existentials I can store Plugin s in the main app, but I cannot unwrap them in the plugin code. |
| 08:30:12 | <quicksilver> | data Plugin s = Plugin { pluginState :: s, initPlugin :: s -> IO (), handleStuff :: s -> IO s, ...} |
| 08:30:12 | <cnwdup> | I could use dynamic but then I cannot benefit from type checking. |
| 08:30:22 | <quicksilver> | cnwdup: wrong. |
| 08:30:35 | <quicksilver> | cnwdup: if you store all the functions which operate on 's' inside the plugin data structure |
| 08:30:49 | <quicksilver> | then the type checker can check all the 's's match. |
| 08:31:58 | <cnwdup> | quicksilver, that might work. I'll see if I can get my code to work with that. Thanks. |
| 08:32:10 | <quicksilver> | sure :) |
| 08:32:18 | <quicksilver> | I've written code very like this to handle particle systems, for example |
| 08:32:26 | <quicksilver> | where the particles can store different kinds of internal state |
| 08:32:31 | <quicksilver> | and the main program doesn't need to know what. |
| 08:32:32 | <JoshTriplett> | I need to keep a mutable table of structures. These structures will consist of a few small numeric values. I'd like as much efficiency as possible. Do I want the uvector package, or something else? |
| 08:33:02 | <cnwdup> | quicksilver, yeah. I've been trying to do this for ages (every now and then) and I never got it to work properly. Hopefully I can get it right now. |
| 08:33:47 | <hatds> | whenever you do data Foo = forall a. Foo (a, a->Int->Int, a->Bool) you could just as well say Foo = forall a. Foo (Int->Int, Bool) |
| 08:33:57 | <hatds> | er, no forall in the 2nd one |
| 08:34:10 | <quicksilver> | hatds: yes, but that's not normally the pattern. |
| 08:34:17 | <quicksilver> | hatds: normally at least one of them returns 'a' |
| 08:34:25 | <quicksilver> | (the "new state" after some kind of processing) |
| 08:34:30 | <Ycros> | hydo: so I did "cabal install time-1.1.2.4" and then "ghc-pkg unregister --force time-1.1.3", unregister will list a bunch of packages that will be broken, so then I did "cabal install --reinstall <list of packages>" |
| 08:34:35 | <Ycros> | hydo: now it's workin |
| 08:34:41 | <hatds> | that's a little different then |
| 08:34:42 | <quicksilver> | forall s. Foo (s, s -> IO s) |
| 08:34:45 | <quicksilver> | for example. |
| 08:35:09 | <hydo> | Ycros: ok... I'll do that tomorrow. sleepy time right now. Thanks for the info! |
| 08:35:11 | <quicksilver> | or possibly data AnyFoo = forall s. Foo (s, s -> IO AnyFoo) |
| 08:35:19 | <quicksilver> | ...which actually allows the mutator to change the state type. |
| 08:35:28 | <quicksilver> | or even data AnyFoo = forall s. Foo (s, s -> IO [AnyFoo]) |
| 08:35:33 | <quicksilver> | which allows the Foos to reproduce. |
| 08:35:49 | <quicksilver> | my particles were in the latter category. |
| 08:36:04 | <quicksilver> | fireworks can explode, producing new particles of a different type. |
| 08:36:35 | <joeally> | what is the fractional exponential (power or index) fucntion |
| 08:36:48 | <quicksilver> | > 10 ** -0.25 |
| 08:36:49 | <lambdabot> | precedence parsing error |
| 08:36:49 | <lambdabot> | cannot mix `(**)' [infixr 8] and pref... |
| 08:36:53 | <quicksilver> | > 10 ** (-0.25) |
| 08:36:55 | <lambdabot> | 0.5623413251903491 |
| 08:36:55 | <joeally> | oh |
| 08:36:56 | <quicksilver> | stupid minus signs. |
| 08:37:09 | <joeally> | i thought that was the floating one |
| 08:37:21 | <quicksilver> | there is also (^^) |
| 08:37:24 | <joeally> | what is the difference between float and fraction |
| 08:37:25 | <joeally> | o |
| 08:37:30 | <joeally> | . |
| 08:37:37 | <joeally> | > :t (^^) |
| 08:37:38 | <lambdabot> | <no location info>: parse error on input `:' |
| 08:37:38 | <quicksilver> | floating supports transcendentals like sin, cos, exp |
| 08:37:46 | <joeally> | okay |
| 08:37:47 | <quicksilver> | fraction just supports times and divide |
| 08:37:56 | <quicksilver> | you need exp for a totally generalised power rule |
| 08:37:57 | <joeally> | i dont need trig functions |
| 08:38:12 | <joeally> | i am doing proabability |
| 08:38:24 | <joeally> | the binomial distribution |
| 08:38:31 | <joeally> | if i use (**) |
| 08:39:11 | <joeally> | i get weird answers with 'e' (assuming that is the number that differentiates to itself) in |
| 08:39:34 | <joeally> | i get this 4.000000000000001e-2 |
| 08:40:08 | <alexey23> | It's just exponentional notation. |
| 08:40:21 | <joeally> | oh |
| 08:40:51 | <joeally> | how do i get just an normal floaring point or fractional notaion |
| 08:40:53 | <alexey23> | <m>e<p> means <m>*10^<p>. |
| 08:41:31 | <joeally> | i thought e was 2.71.... |
| 08:41:59 | <JoshTriplett> | joeally: The 'e' here has nothing to do with the numeric constant 'e'. |
| 08:42:07 | <joeally> | oh |
| 08:42:17 | <JoshTriplett> | joeally: Just a piece of notation. Like the 'd' in d/dx for differentiation. |
| 08:42:30 | <JoshTriplett> | > 1e2 |
| 08:42:30 | <joeally> | oh |
| 08:42:31 | <lambdabot> | 100.0 |
| 08:42:35 | <JoshTriplett> | > 1e4 |
| 08:42:36 | <lambdabot> | 10000.0 |
| 08:42:39 | <joeally> | ahhhhh |
| 08:42:44 | <joeally> | oh i see |
| 08:42:50 | <joeally> | standard form |
| 08:42:58 | <joeally> | is it standard form |
| 08:43:28 | <joeally> | so 4e4 is 4 times to to to the power 4 |
| 08:43:47 | <joeally> | or 4 multiplied by 10 to the power 4 |
| 08:43:49 | <alexey23> | joeally, why don't you use rationals? I think they are enough for the binomial distribution. |
| 08:43:53 | <JoshTriplett> | joeally: The latter. |
| 08:43:57 | <JoshTriplett> | > 4e4 |
| 08:43:59 | <lambdabot> | 40000.0 |
| 08:44:01 | <joeally> | they are the same thing |
| 08:44:25 | <joeally> | alexey23: i dont know how to |
| 08:44:28 | <cnwdup> | quicksilver, can I use existential qualification in the PluginMap type or do I have to use it on the Plugin data structure? |
| 08:44:30 | <joeally> | i'm new to haskell |
| 08:44:39 | <alexey23> | Check Rational. |
| 08:44:43 | <JoshTriplett> | > 1 / 3 |
| 08:44:44 | <lambdabot> | 0.3333333333333333 |
| 08:44:50 | <athos> | > 1 % 3 |
| 08:44:51 | <lambdabot> | 1%3 |
| 08:44:53 | <athos> | :-)))))) |
| 08:44:54 | <JoshTriplett> | > 1 / 3 :: Rational |
| 08:44:55 | <lambdabot> | 1%3 |
| 08:45:02 | <joeally> | oh |
| 08:45:04 | <JoshTriplett> | > 3 * (1/3) |
| 08:45:05 | <lambdabot> | 1.0 |
| 08:45:11 | <athos> | > 3 * 1%3 |
| 08:45:12 | <lambdabot> | 1%1 |
| 08:45:33 | <joeally> | > 4^^0.2 :: Rational |
| 08:45:34 | <lambdabot> | Add a type signature |
| 08:45:36 | <JoshTriplett> | ACTION hoped Haskell would make the classic floating point error there. :) |
| 08:45:38 | <alexey23> | http://www.haskell.org/onlinereport/ratio.html |
| 08:45:47 | <joeally> | > 4 ^^ 0.2 |
| 08:45:48 | <lambdabot> | Add a type signature |
| 08:46:02 | <JoshTriplett> | > 4 ^^ (1/5) :: Rational |
| 08:46:02 | <joeally> | thanks |
| 08:46:03 | <lambdabot> | Add a type signature |
| 08:46:17 | <JoshTriplett> | @type (^^) |
| 08:46:18 | <lambdabot> | forall a b. (Integral b, Fractional a) => a -> b -> a |
| 08:46:24 | <earthy> | whoa! |
| 08:46:24 | <earthy> | n142233:thesparse arthurvl$ ghci +RTS -H1024M -k128M -RTS -isrc |
| 08:46:24 | <earthy> | Segmentation fault |
| 08:47:02 | <earthy> | 'that shouldn't happen' |
| 08:47:15 | <JoshTriplett> | earthy: Awesome. That gives me a somewhat more descriptive error... |
| 08:47:21 | <joeally> | it shouldnt |
| 08:47:22 | <JoshTriplett> | ghc: internal error: splitLargeBlock: not a multiple of a megablock |
| 08:47:41 | <earthy> | n142233:thesparse arthurvl$ ghci -isrc +RTS -k128M |
| 08:47:41 | <earthy> | Too late for parseStaticFlags: call it before newSession |
| 08:47:55 | <earthy> | what the ?! |
| 08:48:14 | <JoshTriplett> | I can reproduce the problem with just this: ghci +RTS -k128M -RTS |
| 08:48:19 | <earthy> | ACTION nods |
| 08:48:26 | <earthy> | ofcourse, it kinda makes sense |
| 08:48:35 | <earthy> | as 128M doesn't fit in 8M |
| 08:48:36 | <earthy> | but still... |
| 08:48:52 | <earthy> | 'segmentation fault' is not the answer I expected. :) |
| 08:49:01 | <JoshTriplett> | earthy: Indeed. |
| 08:49:55 | <sjanssen> | I can't reproduce this |
| 08:50:11 | <earthy> | sjanssen: I'm on Mac OS X |
| 08:50:27 | <sjanssen> | earthy: where does 8M come from? |
| 08:50:35 | <earthy> | The Glorious Glasgow Haskell Compilation System, version 6.10.2 |
| 08:50:46 | <JoshTriplett> | earthy: Ditto here. |
| 08:50:49 | <earthy> | sjanssen: the default max stack size |
| 08:50:50 | <JoshTriplett> | Actually... |
| 08:50:55 | <JoshTriplett> | I take that back. |
| 08:50:56 | <JoshTriplett> | The Glorious Glasgow Haskell Compilation System, version 6.10.1 |
| 08:51:17 | <earthy> | sjanssen: -k sets the per-thread stack size, but the default max stack size according to the docs is 8M |
| 08:51:19 | <sjanssen> | oh, lower case k |
| 08:51:27 | <earthy> | ACTION nods |
| 08:51:29 | <earthy> | innocent type |
| 08:51:30 | <earthy> | typo |
| 08:51:44 | <sjanssen> | funny bug |
| 08:51:51 | <earthy> | ACTION nods |
| 08:52:26 | <sjanssen> | 6.8.2 seems to be fine |
| 08:52:50 | <sjanssen> | 6.10.1 crashes with "ghc: internal error: splitLargeBlock: not a multiple of a megablock" |
| 08:53:11 | <pumpkin> | onoes, not a megablock! |
| 08:53:22 | <JoshTriplett> | How many of those in a gigaquad? ;) |
| 08:53:35 | <quicksilver> | cnwdup: I'm not sure I understand your question but I think you'll want to use it on the Plugin structure |
| 08:53:58 | <joeally> | **sighs |
| 08:57:47 | <cnwdup> | quicksilver, but then I cannot call functions of the Plugin structure from main and I want to call functions like pluginName. I do not want to call functions which operate on the state, though. |
| 08:58:21 | <cnwdup> | Do I have to seperate the function call-able from main and the functions only call-able from the plugins then? |
| 08:59:08 | <quicksilver> | cnwdup: can you paste some type signatures or some names or something? It's a little hard to explain without something concrete to talk about |
| 08:59:49 | <cnwdup> | Ok. Sec |
| 09:00:10 | <mib_uk2x9xa6> | > Just Nothing |
| 09:00:10 | <joeally> | what does this mean "*** Exception: stack overflow" |
| 09:00:11 | <lambdabot> | Just Nothing |
| 09:00:28 | <ivanm> | joeally: you used up too much memory |
| 09:00:31 | <PetRat> | > join $ Just Nothing |
| 09:00:33 | <lambdabot> | Nothing |
| 09:00:40 | <joeally> | oh |
| 09:01:05 | <PetRat> | join $ Just Just Just Nothing |
| 09:01:09 | <joeally> | oh i spotted the problem |
| 09:01:14 | <ivanm> | heh |
| 09:01:14 | <koeien> | PetRat: it removes one level |
| 09:01:23 | <joeally> | i did unending reoccursion |
| 09:01:24 | <dibblego> | > join $ Just $ Just Nothing |
| 09:01:25 | <PetRat> | > join $ Just Just Just Nothing |
| 09:01:25 | <lambdabot> | Just Nothing |
| 09:01:26 | <lambdabot> | Couldn't match expected type `(a1 -> Maybe a1) |
| 09:01:37 | <athos> | > join $ [[a]] |
| 09:01:38 | <lambdabot> | [a] |
| 09:01:38 | <ivanm> | joeally: yeah, that's a common cause |
| 09:01:40 | <dibblego> | > join $ join $ Just $ Just Nothing |
| 09:01:41 | <lambdabot> | Nothing |
| 09:02:05 | <PetRat> | > join $ Just $ Just $ Just Nothing |
| 09:02:06 | <lambdabot> | Just (Just Nothing) |
| 09:02:15 | <joeally> | oh so i'll no that will proably be the problem |
| 09:03:13 | <PetRat> | Besides lists and Maybe, what other monads provide simple examples for join? |
| 09:03:35 | <koeien> | identity monad :) |
| 09:03:36 | <ivanm> | the identity monad? |
| 09:03:38 | <ivanm> | heh |
| 09:03:59 | <koeien> | PetRat: that is the reason that in haskell, monads are most often described using (>>=) and return. |
| 09:04:10 | <koeien> | while in category theory, one uses return & join most of the time. |
| 09:04:43 | <PetRat> | koeien: can you amplify? what is the reason? |
| 09:05:08 | <dibblego> | ((->) t) |
| 09:05:11 | <ivanm> | is "because" good enough? ;-) |
| 09:05:22 | <koeien> | PetRat: ehm, (>>=) is more intuitive for more monads |
| 09:05:23 | <ivanm> | dibblego: oh? what's join on ((->) t) ? |
| 09:05:27 | <ivanm> | function composition? |
| 09:05:29 | <PetRat> | koeien said "that is the reason" |
| 09:05:34 | <dibblego> | @type join :: (t -> t -> a) -> t -> a |
| 09:05:36 | <lambdabot> | forall t a. (t -> t -> a) -> t -> a |
| 09:05:38 | <PetRat> | so probably some reason is in mind |
| 09:05:41 | <yitz> | > join (*) 5 |
| 09:05:43 | <lambdabot> | 25 |
| 09:06:07 | <cnwdup> | quicksilver, http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2451#a2451 |
| 09:06:12 | <ivanm> | dibblego: just uses the one value everywhere? |
| 09:06:13 | <yitz> | > join (,) "foo" |
| 09:06:16 | <lambdabot> | ("foo","foo") |
| 09:06:21 | <koeien> | PetRat: >>= is easier to reason about "action composition", whereas join might be easier to reason about mathematically |
| 09:06:26 | <dibblego> | @djinn (t -> t -> a) -> t -> a |
| 09:06:27 | <lambdabot> | f a b = a b b |
| 09:06:45 | <quicksilver> | > runWriter . join $ Writer(Writer (100, ["hello"]),["world"]) |
| 09:06:46 | <lambdabot> | (100,["world","hello"]) |
| 09:06:55 | <quicksilver> | PetRat: maybe that's also fairly simple? |
| 09:07:01 | <quicksilver> | although the runWriter/Writer noise is noisy. |
| 09:07:18 | <PetRat> | So join on a function that takes two arguments puts the value there twice. join (*) 5 |
| 09:07:31 | <dibblego> | PetRat, prexactly |
| 09:07:34 | <koeien> | from the Haskell wiki, "↑ This is perhaps due to the fact that Haskell programmers like to think of monads as a way of sequencing computations with a common feature, whereas in category theory the container aspect of the various structures is emphasised. join pertains naturally to containers (squashing two layers of a container down into one), but (>>=) is the natural sequencing operation (do something, feeding its results into something else)" |
| 09:08:21 | <PetRat> | So you are putting a Writer monad in a Writer monad? |
| 09:08:32 | <quicksilver> | cnwdup: OK, so you also need something like data AnyPlugin = forall s . AnyPlugin (Plugin s) |
| 09:08:38 | <ivanm> | please, no "dawg" meme references... |
| 09:08:48 | <pumpkin> | ACTION clears throat |
| 09:08:52 | <cnwdup> | quicksilver, ok |
| 09:08:57 | <quicksilver> | cnwdup: and you will need getPlugin to return AnyPlugin |
| 09:09:29 | <quicksilver> | cnwdup: but, your code implies that pluginB "knows" that pluginA has state type Int |
| 09:09:40 | <PetRat> | What is the exact type of that writer? Writer Int [String]? |
| 09:09:40 | <quicksilver> | that's not going to work under this system. |
| 09:09:40 | <ivanm> | pumpkin: down, boy! ;-) |
| 09:09:57 | <quicksilver> | PetRat: Writer [String] Int, in fact. |
| 09:10:12 | <quicksilver> | the "log" comes before the "contained value" |
| 09:10:39 | <quicksilver> | cnwdup: because 'getPlugin' has already lost the information that pluginA has state type Int. |
| 09:11:15 | <PetRat> | What properties of a monad mean you can put another one inside it? It would be a parameterized monad with the appropriate type properties on the parameter? |
| 09:11:16 | <pumpkin> | :) |
| 09:11:21 | <cnwdup> | quicksilver, could I have something like getPlugin :: Plugin s -> m (Plugin s) where I would call the plugin depending on the plugin's type? Then the plugin's type should be unique which should be doable. |
| 09:11:33 | <pumpkin> | I think xzibit probably invented join |
| 09:11:41 | <pumpkin> | actually |
| 09:11:47 | <quicksilver> | cnwdup: you could even have simply getPlugin :: m (Plugin s) |
| 09:11:52 | <fasta> | quicksilver: I tried to run it with the debugger and pressing C-c to stop the infinite loop, btw. The result was a segmentation fault ^^. |
| 09:11:59 | <cnwdup> | quicksilver, how would that work? |
| 09:12:03 | <quicksilver> | cnwdup: which would 'automatically' return the right plugin based on type inference. |
| 09:12:12 | <quicksilver> | cnwdup: well, in practice you'd need a class for it |
| 09:12:23 | <quicksilver> | getPlugin :: RegisteredType s => m (Plugin s) |
| 09:12:38 | <quicksilver> | and the class would 'know' where to find the canonical plugins of each type. |
| 09:12:42 | <quicksilver> | somehow. |
| 09:12:43 | <pumpkin> | actually, xzibit probably did the opposite of join (duplicate) in Control.Comonad |
| 09:12:50 | <cnwdup> | quicksilver, what kind of structure would I use to store the plugins? After all they have a mutable state. |
| 09:12:50 | <quicksilver> | fasta: ops :) |
| 09:13:07 | <quicksilver> | cnwdup: well maybe you need have IORef s instead of just s. |
| 09:13:23 | <quicksilver> | cnwdup: or maybe you need the whole thing to be in an IORef, as in IORef (Plugin s) |
| 09:13:33 | <quicksilver> | depends how much cna mutate. |
| 09:14:14 | <cnwdup> | quicksilver, ok. I'll need some time to think about that, though. |
| 09:14:55 | <PetRat> | Is "Either s" defined as a monad somewhere? |
| 09:14:58 | <pumpkin> | ACTION proposes that we rename duplicate :: w a -> w (w a) in Control.Comonad to yodawg |
| 09:15:18 | <idnar> | PetRat: unfortunately not, but (Error s) => Either s is defined in Control.Monad.Instances |
| 09:16:03 | <PetRat> | idnar: what does that notation mean? (Error s) => Either s |
| 09:16:13 | <quicksilver> | cnwdup: agreed. It is all possible but it's not obvious what the right path is without a little more info. |
| 09:16:14 | <dibblego> | s belongs to the type-class Error |
| 09:17:51 | <cnwdup> | quicksilver, I'll try to find a solution myself. If I run into trouble then I should at least be able to provide more information. |
| 09:18:26 | <quicksilver> | cnwdup: another possibility is simply to have pluginA provide a "global" to get itself. |
| 09:18:34 | <quicksilver> | GetPluginA :: PL (Plugin Int) |
| 09:18:50 | <quicksilver> | cnwdup: obviously the main program doesn't "know about" pluginA, so it would never call that. |
| 09:19:08 | <quicksilver> | cnwdup: but if pluginB is specifically designed to know about pluginA, then it knows that symbol and can get it type-safelu. |
| 09:19:16 | <ahamay42> | PetRat: You can also just do the declaration yourself (nice practice) |
| 09:19:21 | <cnwdup> | But pluginB could call that, right? Then it would be okay to index plugins by plugin names (String)? |
| 09:20:11 | <quicksilver> | cnwdup: you don't even need Strings, for this. |
| 09:20:21 | <quicksilver> | cnwdup: GetPluginA is a standard haskell value |
| 09:20:30 | <quicksilver> | cnwdup: it's just a question of module imports, then. |
| 09:20:38 | <quicksilver> | PluginB does "import PluginA(GetPluginA)" |
| 09:20:48 | <quicksilver> | so PluginB has a type-safe way of getting pluginA |
| 09:21:08 | <cnwdup> | But how would it get the state? I have to ask the main application for that. |
| 09:21:11 | <quicksilver> | whereas, if you use the generic version : getPlugin "PluginA" |
| 09:21:43 | <quicksilver> | you get an AnyPlugin |
| 09:21:49 | <quicksilver> | which is useful for some things, but not for others. |
| 09:21:58 | <quicksilver> | I.e. you can't call handleStuff, because that needs exact type knowledge |
| 09:22:04 | <quicksilver> | but you can call the other things where it doesn't matte.r |
| 09:22:20 | <cnwdup> | But pluginB needs to call handleStuff on pluginA. |
| 09:22:44 | <quicksilver> | yes. |
| 09:22:49 | <Smorg> | How do you clean out all temporarily defined functions in ghci? (e.g. let foo = some func) |
| 09:22:50 | <quicksilver> | which it can, because it has access to GetPluginA |
| 09:22:56 | <quicksilver> | which returns the type-correct one. |
| 09:23:04 | <cnwdup> | quicksilver, ah! Okay. Thanks. (: |
| 09:23:06 | <quicksilver> | So effectively, you have two ways of getting PluginA |
| 09:23:17 | <quicksilver> | getPlugin "PluginA" :: PL AnyPlugin |
| 09:23:25 | <quicksilver> | getPluginA :: PL (Plugin Int) |
| 09:23:26 | <cnwdup> | So I have one way to get the function and one way to get the value of the state. |
| 09:23:40 | <quicksilver> | the first way works from any module, but you don't have access to the type info |
| 09:23:50 | <quicksilver> | the second way only works from modules which import PluginA's interface |
| 09:23:57 | <quicksilver> | i.e they have to "know about" pluginA. |
| 09:24:35 | <Ferdirand> | 1 |
| 09:24:37 | <Ferdirand> | oops |
| 09:27:48 | <quicksilver> | cnwdup: it still remains to answer the question of what a Plugin "is", where they are actually stored, and which part is mutable. |
| 09:28:05 | <quicksilver> | but this questions too surely have answers :) |
| 09:28:05 | <cnwdup> | I hope I can figure that out myself. |
| 09:31:44 | <dibblego> | the unit for a Parser :: String -> (String, Maybe a) would be \a s -> (s, Just a) right? |
| 09:33:39 | <quicksilver> | yes. That consumes nothing of the input and always successfully returns a |
| 09:35:27 | <joeally> | I am doing a poisson distribution how do i get the mathematical constant 'e' |
| 09:35:33 | <quicksilver> | > exp 1 |
| 09:35:34 | <lambdabot> | 2.718281828459045 |
| 09:35:39 | <joeally> | cheers |
| 09:35:47 | <joeally> | > exp 2 |
| 09:35:48 | <lambdabot> | 7.38905609893065 |
| 09:35:51 | <joeally> | ohh |
| 09:35:52 | <quicksilver> | that's e^2 |
| 09:35:54 | <quicksilver> | ;) |
| 09:35:55 | <joeally> | oh |
| 09:35:58 | <joeally> | i get it |
| 09:35:59 | <joeally> | thanks |
| 09:36:11 | <DrSyzygy> | > exp (log 3) |
| 09:36:12 | <lambdabot> | 3.0000000000000004 |
| 09:36:17 | <Zao> | (derive . e) 1 :P |
| 09:36:23 | <DrSyzygy> | > exp (log 3) :: CReal |
| 09:36:24 | <lambdabot> | 3.0 |
| 09:52:57 | <Smorg> | > [y+1 | y <- x, y < 10] |
| 09:52:58 | <lambdabot> | Couldn't match expected type `[t]' against inferred type `Expr' |
| 09:53:17 | <ivanm> | Smorg: need to define what "x" is... |
| 09:54:51 | <paul424> | what does it mean in haskell the sentence a::b for types ... that a is subtype of b right ? |
| 09:55:00 | <pumpkin> | no |
| 09:55:06 | <pumpkin> | identifier a is of type b |
| 09:55:24 | <ray> | :t drunkard |
| 09:55:25 | <lambdabot> | Not in scope: `drunkard' |
| 09:55:33 | <paul424> | pumpkin: aha ok thanks |
| 09:57:31 | <ivanm> | with ReadS, how does one denote a "failed" read? Can you? |
| 09:57:40 | <Smorg> | ivanm: interesting this bot catches an error. If I let x = 1 : [y+1 | y <- x] I get an unbounded infinite list. If x = 1 : [y+1 | y <- x, x<10] then it actually prints something but still seems to be unbounded: [2,3,4,5,6,7,8,9,10^CInterrupted. |
| 09:57:48 | <ivanm> | or would you use "ReadS (Maybe a)" ? |
| 09:58:04 | <ivanm> | Smorg: it does? that's weird... |
| 09:58:14 | <pumpkin> | > let x = 1 : [y+1 | y <- x] in x |
| 09:58:15 | <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... |
| 09:58:28 | <ivanm> | oh, I didn't see the ":" |
| 09:58:30 | <Smorg> | (in ghci) |
| 09:58:54 | <ivanm> | Smorg: because it's a recursive definition for x |
| 09:58:55 | <pumpkin> | Smorg: it's still going to keep looking |
| 09:59:05 | <PetRat> | http://www.mibbit.com/pb/5msXLq Is this the right definition of "Either s" as an instance of Monad? |
| 09:59:15 | <pumpkin> | it isn't smart enough to tell that element 10000000000000000000 won't be < 10 again |
| 09:59:18 | <ivanm> | the error is that you didn't have "let x = 1 :" in what you gave to lambdabot |
| 09:59:33 | <dmwit> | ivanm: failure is (const []), no? |
| 10:00:04 | <ivanm> | dmwit: hmmm.... I was hoping more for a "trial parsing", where it returned the String if it couldn't parse |
| 10:00:25 | <ivanm> | *shrug* but "const []" works as well... just can't chuck the String away, that's all |
| 10:00:40 | <dmwit> | PetRat: Looks good to me. |
| 10:01:12 | <Smorg> | Yeah i've been working all day trying to figure out a smart way to test for equivilence for hilbert's hotel-ish problems since that seems to be a major reason for why you would want to have such an infinite construct. |
| 10:01:15 | <dmwit> | PetRat: In actual Haskell, we have to add a "fail" function; this is why the Either instance usually comes with an Error constraint. |
| 10:01:23 | <Smorg> | > [0,2..] ++ [1,3..] == [0..] |
| 10:01:24 | <lambdabot> | False |
| 10:01:57 | <PetRat> | What does the fail look like? |
| 10:02:02 | <pumpkin> | > merge [0,2..] [1,3..] == [0..] |
| 10:02:03 | <lambdabot> | Not in scope: `merge' |
| 10:03:13 | <PetRat> | Smorg: are you asking lambdabot to do something in the realm of proof? |
| 10:03:25 | <pumpkin> | it's not even true |
| 10:03:53 | <Smorg> | > (sort([0,2..] ++ [1,3..)) == [0..] |
| 10:03:54 | <lambdabot> | <no location info>: parse error on input `)' |
| 10:04:10 | <Smorg> | yes basically proof |
| 10:05:20 | <dmwit> | PetRat: Something like fail = Left . strMsg |
| 10:05:21 | <ivanm> | Smorg: well, Haskell doesn't really work too well for automatic proofs like that |
| 10:05:22 | <Smorg> | > (sort([0,2..] ++ [1,3..])) == [0..] |
| 10:05:22 | <dmwit> | :t strMsg |
| 10:05:24 | <lambdabot> | forall a. (Error a) => String -> a |
| 10:05:25 | <ivanm> | see Coq, etc. |
| 10:05:30 | <ivanm> | @instances Error |
| 10:05:40 | <ivanm> | come on, lambdabot... |
| 10:05:59 | <pumpkin> | @instances-importing Error |
| 10:05:59 | <lambdabot> | Couldn't find class `Error'. Try @instances-importing |
| 10:06:01 | <lambdabot> | thread killed |
| 10:06:01 | <Ferdirand> | Tho0uLe8ieHin7iequeilioth |
| 10:06:06 | <pumpkin> | o.O |
| 10:06:09 | <Ferdirand> | oops |
| 10:06:13 | <pumpkin> | o.O |
| 10:06:14 | <ivanm> | @hoogle Error |
| 10:06:20 | <dmwit> | ?instances-importing Control.Monad.Error Error |
| 10:06:22 | <pumpkin> | sounds like you need a new passphrase :P |
| 10:06:30 | <ivanm> | hmmm... lambdabot sure is slow tonight... |
| 10:06:31 | <Smorg> | with coq I need to learn more logic :( |
| 10:06:46 | <lambdabot> | Couldn't find class `Error'. Try @instances-importing |
| 10:06:56 | <lambdabot> | module Control.Monad.Error |
| 10:07:01 | <lambdabot> | module Foreign.C.Error |
| 10:07:05 | <lambdabot> | module Foreign.Marshal.Error |
| 10:07:05 | <pumpkin> | Smorg: I don't think any system could tell you that without having lots of information already |
| 10:07:07 | <lambdabot> | Plugin `instances' failed with: thread killed |
| 10:07:24 | <pumpkin> | Smorg: ...not even WOLFRAM ALPHA ;) |
| 10:07:27 | <yitz> | > concat (zipWith (\x y -> [x,y]) [0,2..] [1,3..]) == [0..] |
| 10:08:04 | <dmwit> | > concat (transpose [[0,2..], [1,3..]]) == [0..] |
| 10:08:19 | <lambdabot> | thread killed |
| 10:08:33 | <PetRat> | http://www.mibbit.com/pb/SEPxIX Here is an example of using Either s as a Monad. A result of "Left .." short-circuits the computation. The case statement is awkward because it requires giving a result for the "Right" case that is discarded. |
| 10:08:45 | <yitz> | oh, we shouldn't abuse \bot with these things if she's feeling out of sorts |
| 10:08:53 | <dmwit> | But more seriously: no, the purpose of infinite data is not for doing infinite proofs. |
| 10:09:25 | <Smorg> | I'm sure this runs into russel's paradox-esque problems mathematically. |
| 10:09:44 | <ivanm> | @seen lambdabot |
| 10:09:44 | <lambdabot> | Yes, I'm here. I'm in ##hrg, #unicycling, #scannedinavian, #scala, #rosettacode, #perl6, #macosxdev, #jtiger, #jhc, #haskell_ru, #haskell.se, #haskell.ru, #haskell.no, #haskell.jp, #haskell.it, # |
| 10:09:44 | <lambdabot> | haskell.hr, #haskell.fr, #haskell.fi, #haskell.es, #haskell.dut, #haskell.de, #haskell.cz, #haskell-soc, #haskell-books, #haskell-blah, #haskell-in-depth, #haskell-freebsd, #macosx, ##freebsd, # |
| 10:09:44 | <lambdabot> | gentoo-uy, #gentoo-haskell, #friendly-coders, #dreamlinux-es, #concatenative, #arch-haskell, #functionaljava, #novalang, #darcs, #yi, #xmonad, #ghc, ##logic, #haskell-overflow and #haskell |
| 10:10:14 | <ivanm> | ACTION thinks lambdabot needs to cut down on how many IRC channels she idles in... |
| 10:10:30 | <lilac> | the idea of #functionaljava scares me |
| 10:10:30 | <lambdabot> | lilac: You have 3 new messages. '/msg lambdabot @messages' to read them. |
| 10:10:35 | <ivanm> | really, functionaljava? I thought Java was the archenemy... |
| 10:10:42 | <ivanm> | lilac: heh |
| 10:11:13 | <dmwit> | PetRat: That's an example, I guess, though I wouldn't say it's a particularly compelling one. |
| 10:11:21 | <Lemmih> | @leave jhc |
| 10:11:35 | <ivanm> | maybe we need to split lambdabot into multiple instances... haskell channels, and non-haskell channels |
| 10:11:51 | <Lemmih> | @leave #jhc |
| 10:11:52 | <PetRat> | dmwit: I guess it's more common to use Error in these circumstances? |
| 10:11:57 | <pumpkin> | Lemmih: I think it's @part |
| 10:12:02 | <pumpkin> | unless @leave is working |
| 10:12:10 | <lilac> | @tell roconnor gah, you and your non-commutative addition... ;-) |
| 10:12:11 | <lambdabot> | Consider it noted. |
| 10:12:11 | <ivanm> | Lemmih: apparently, that channel doesn't exist if I try and do /topic to it... >_> |
| 10:12:41 | <dmwit> | PetRat: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5069#a5069 |
| 10:13:17 | <dmwit> | PetRat: It's not a good example because it isn't replacing any nested cases. ;-) |
| 10:13:32 | <yitz> | @seen lambdabot |
| 10:13:32 | <lambdabot> | Yes, I'm here. I'm in ##hrg, #unicycling, #scannedinavian, #scala, #rosettacode, #perl6, #macosxdev, #jtiger, #haskell_ru, #haskell.se, #haskell.ru, #haskell.no, #haskell.jp, #haskell.it, #haskell. |
| 10:13:32 | <lambdabot> | hr, #haskell.fr, #haskell.fi, #haskell.es, #haskell.dut, #haskell.de, #haskell.cz, #haskell-soc, #haskell-books, #haskell-blah, #haskell-in-depth, #haskell-freebsd, #macosx, ##freebsd, #gentoo-uy, # |
| 10:13:32 | <lambdabot> | gentoo-haskell, #friendly-coders, #dreamlinux-es, #concatenative, #arch-haskell, #functionaljava, #novalang, #darcs, #yi, #xmonad, #ghc, ##logic, #haskell-overflow and #haskell |
| 10:14:17 | <PetRat> | I see that this example is easier to do without the monad. |
| 10:15:30 | <yaxu> | Hi all, I'm playing around with hint (Data.Haskell.Interpreter), and would like to interpret a string into a value of type Int -> [String] |
| 10:15:47 | <cnwdup> | > data Foo a = (Num a) => Foo a |
| 10:15:49 | <lambdabot> | <no location info>: parse error on input `data' |
| 10:16:04 | <Smorg> | > all (>=0) [0..] |
| 10:16:10 | <cnwdup> | Can I have type constraints on data types? |
| 10:16:13 | <Smorg> | yep definitely not going to work then |
| 10:16:19 | <lambdabot> | thread killed |
| 10:16:20 | <yaxu> | however it won't let me do that, because Int -> [String] isn't an instance of class Typable |
| 10:16:24 | <quicksilver> | cnwdup: Yes. Don't do it though. |
| 10:16:28 | <dmwit> | cnwdup: Yes, but it's generally frowned upon. |
| 10:16:39 | <cnwdup> | ok |
| 10:16:45 | <yaxu> | is it possible to make it an instance, and if so how would I go about doing that? |
| 10:16:59 | <quicksilver> | > typeOf (\a -> show (a :: Int)) |
| 10:17:01 | <lambdabot> | Int -> [Char] |
| 10:17:11 | <PetRat> | yaxu: can you say more about why you are doing this? |
| 10:17:12 | <quicksilver> | yaxu: Int -> [String] is indeed an instance of Typeable. |
| 10:17:18 | <quicksilver> | > typeOf (\a -> [show (a :: Int)]) |
| 10:17:21 | <lambdabot> | Int -> [[Char]] |
| 10:17:33 | <quicksilver> | (typeOf uses Typeable, so it must be) |
| 10:18:27 | <PetRat> | :t typeOf |
| 10:18:29 | <lambdabot> | forall a. (Typeable a) => a -> TypeRep |
| 10:18:39 | <fasta> | What does a gigantic Foo.CAF mean in a heap profile? |
| 10:18:41 | <yaxu> | PetRat: I'd like to make a music interface where dynamically interpreted haskell code is turned into musical patterns |
| 10:19:02 | <yaxu> | quicksilver: hm, let me find the error message I'm getting then |
| 10:19:27 | <PetRat> | Music! That's my ultimate interest in Haskell as well. Computer-assisted composition. |
| 10:20:05 | <dmwit> | Man, I don't even remember what CAF stands for. |
| 10:20:12 | <pumpkin> | constant applicative form doesn't it? |
| 10:20:33 | <yaxu> | PetRat: nice, have you looked as hsc3? |
| 10:20:42 | <dmwit> | Right, that's it. |
| 10:20:58 | <fasta> | pumpkin: yes, but I already knew that part. |
| 10:21:10 | <yaxu> | tsch, I was doing something stupid. Sorry and thanks quicksilver |
| 10:21:22 | <pumpkin> | fasta: it means you have a large constant taking up all your memory somewhere because it isn't getting GCed |
| 10:21:25 | <pumpkin> | fasta: I'd assume |
| 10:21:26 | <fasta> | pumpkin: you get the same when you do primes = <insert create all primes> |
| 10:21:32 | <pumpkin> | yeah |
| 10:22:04 | <fasta> | pumpkin: except, that I don't have something like that in my program, atleast probably it is lurking somewhere, but I have no idea where. |
| 10:30:51 | <lilac> | @seen augustss |
| 10:30:58 | <pumpkin> | NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO |
| 10:31:02 | <pumpkin> | they killed lambdabot |
| 10:31:05 | <lilac> | @seen augustss |
| 10:31:11 | <lambdabot> | augustss is in #haskell. I don't know when augustss last spoke. |
| 10:31:20 | <augustss> | I'm here |
| 10:31:28 | <fasta> | There should be a library somewhere having a function which races a list of IO computations and returns the one which finished the earliest. What's its name? Hoogle/Hayoo didn't work for [IO ()] -> IO() |
| 10:31:28 | <lilac> | @yow! and WIPED LAMBDABOT'S MIND! |
| 10:31:35 | <lambdabot> | YOW!! What should the entire human race DO?? Consume a fifth of |
| 10:31:43 | <lambdabot> | CHIVAS REGAL, ski NUDE down MT. EVEREST, and have a wild SEX WEEKEND! |
| 10:32:03 | <lilac> | augustss: i've uploaded a new version of the 'numbers' package with a more correct Enum instance |
| 10:32:09 | <lilac> | for Natural |
| 10:32:11 | <lambdabot> | lilac: You have 3 new messages. '/msg lambdabot @messages' to read them. |
| 10:32:17 | <p_l> | Baughn: Please don't follow lambdabot's advice... please |
| 10:32:26 | <augustss> | lilac: Oh, was Enum broken? |
| 10:32:52 | <p_l> | ACTION read that as "what would erase human race" ;D |
| 10:32:52 | <lilac> | augustss: yep, it was using the defaults for everything, which really don't work for infinity :) |
| 10:33:01 | <augustss> | Ah, yes. |
| 10:33:09 | <augustss> | Thanks! |
| 10:33:17 | <lilac> | np |
| 10:33:59 | <doserj> | fasta: sth like http://code.haskell.org/unamb/src/Data/Unamb.hs ? |
| 10:34:41 | <ManateeLazyCat> | If i use GADTs create "data PageBuffer a where ... ", how to i create instance of `PageBuffer`? |
| 10:35:00 | <quicksilver> | ManateeLazyCat: using one of the constructors you defined in your GADT? |
| 10:35:01 | <pumpkin> | instance? |
| 10:35:44 | <fasta> | doserj: it's not exactly the same as the function I had written 2 years ago, but it will probably work. |
| 10:36:22 | <lilac> | fasta: foldr race (newEmptyMVar >>= takeMVar) ? |
| 10:36:45 | <Baughn> | @index ClockTime |
| 10:36:47 | <Baughn> | @index ClockTime |
| 10:36:47 | <lambdabot> | System.Time |
| 10:36:50 | <lilac> | that should probably be foldM :) |
| 10:38:11 | <ManateeLazyCat> | quicksilver: I have exist module use `Dynamic` reference different TYPE object, so i don't know how to use GADTs instead `Dynamic`, I want keep *reference* those objects, but those objects are different type. |
| 10:38:45 | <ManateeLazyCat> | quicksilver: I think i haven't understand how to use GADTs. |
| 10:41:27 | <eu-prleu-peupeu> | hi |
| 10:41:30 | <eu-prleu-peupeu> | now im coding in python |
| 10:41:35 | <eu-prleu-peupeu> | in my job |
| 10:41:40 | <ManateeLazyCat> | quicksilver: Any idea? |
| 10:42:02 | <eu-prleu-peupeu> | i still haven't got used to the "return" in python :( i guess haskell makes more sense after you get used to it |
| 10:45:54 | <cnwdup> | quicksilver, I am trying to use a plugin record which is the interface the main application uses for plugins. http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=2452#a2452 What's wrong with pluginRecUpdateState? ghc tells me type variables are escaping. |
| 10:48:21 | <quicksilver> | ManateeLazyCat: your question doesn't make sense to me I'm afraid. |
| 10:49:05 | <quicksilver> | cnwdup: there's nothing wrong with what you've written int hat paste. |
| 10:49:17 | <cnwdup> | I cannot use :t pluginRecUpdateState in ghci. |
| 10:49:29 | <quicksilver> | yes |
| 10:49:30 | <cnwdup> | I think I cannot access the records fields containing s. |
| 10:49:36 | <quicksilver> | record seletors don't work well with existentials |
| 10:49:49 | <quicksilver> | it's best to make a two-stage process |
| 10:49:54 | <cnwdup> | Ah, but pattern matching will work? |
| 10:50:01 | <quicksilver> | should do, yes. |
| 10:50:10 | <eu-prleu-peupeu> | pattern matching :) |
| 10:50:36 | <cnwdup> | Oh my, I thought there's no way to use such functions because of existential types. O: |
| 10:52:07 | <quicksilver> | cnwdup: I normally do the existential in a separate type - and only that, in that type. |
| 10:52:20 | <quicksilver> | cnwdup: so I'd do data PluginRec s = { ... stuff with selectors .. } |
| 10:52:37 | <quicksilver> | data AnyPluginRec = forall s . AnyPluginRec (PluginRec s) |
| 10:53:00 | <cnwdup> | How would I access the plugin's state from the main application? |
| 10:53:16 | <cnwdup> | s/access/change/ |
| 10:53:29 | <cnwdup> | Nope. Actually access and change. |
| 10:54:08 | <quicksilver> | well, what could you possibly change it to? since you don't know what type it is ;) |
| 10:54:32 | <quicksilver> | but for example, if your PluginRec structure had a field of type "s -> s" then you could apply that to the value |
| 10:54:37 | <quicksilver> | and stuff the result back in the IORef. |
| 10:55:45 | <cnwdup> | ok |
| 11:01:05 | <Baughn> | :t threadDelay |
| 11:01:06 | <lambdabot> | Not in scope: `threadDelay' |
| 11:01:13 | <Baughn> | :t Control.Concurrent.threadDelay |
| 11:01:14 | <lambdabot> | Int -> IO () |
| 11:04:23 | <helmut> | Hi. I'm trying to implement suffix trees in haskell and I generally hit stack space limits. could someone have a look for improvements? http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5070 |
| 11:05:07 | <Berengal> | helmut: Make the structure stricter |
| 11:06:24 | <helmut> | I know that it isn't strict enought, but how to improve? |
| 11:07:06 | <Berengal> | You could make some of the fields in your data structure strict |
| 11:07:23 | <helmut> | uhm. I don't understand that |
| 11:08:09 | <helmut> | for instance Common should not permit an empty String. |
| 11:16:53 | <solidsnack> | hello? |
| 11:19:43 | <dcoutts_> | fasta: right, it was just a quick demo. If you're using it seriously you might want to spend a couple hours making it robust and possibly even replacing the parser |
| 11:19:44 | <dcoutts_> | fasta: a decent version could be released as a separate package on hackage |
| 11:23:56 | <Smorg> | Does the empty list in haskell not act like the empty list in set theory since (elem [] [[1],[]] == True) but (elem [] [[1]] == False) ? |
| 11:24:32 | <BONUS> | nope |
| 11:25:24 | <Smorg> | :) |
| 11:28:15 | <solidsnack> | Smorg: The "empty list" in Set theory, or the "empty set"? |
| 11:28:36 | <Smorg> | empty set |
| 11:28:53 | <Smorg> | oops didn't notice I said empty list. |
| 11:30:09 | <solidsnack> | So if I do unsafePerformIO to get an IORef and pass it around, how bad is that? |
| 11:30:41 | <Smorg> | so with that exception nup any list is the same as the definition of a set |
| 11:31:16 | <solidsnack> | Smorg: Lists can contain duplicates. |
| 11:32:27 | <ziman> | Smorg, well, there's difference between \subseteq and \in, in set theory, {} ∉ {{1}} as well |
| 11:32:41 | <Smorg> | s/nup/nub |
| 11:32:57 | <solidsnack> | Smorg: Oh, I understand now. |
| 11:34:03 | <ziman> | > [] `isInfixOf` "foo bar baz" |
| 11:34:06 | <lambdabot> | True |
| 11:34:10 | <ziman> | > [] `elem` "foo bar baz" |
| 11:34:11 | <lambdabot> | Couldn't match expected type `[a]' against inferred type `Char' |
| 11:34:24 | <dcoutts_> | solidsnack: using unsafePerformIO within your program is generally wrong |
| 11:34:34 | <solidsnack> | dcoutts: Yes, I know. |
| 11:35:21 | <dcoutts_> | solidsnack: the only excuses are for low level hacks hidden behind nice interfaces, not within the main body of your code |
| 11:35:23 | <Smorg> | heh how do you get infix? I thought it was in the list module but it doesn't seem to exist for me. isPrefixOf and isSuffixOf work |
| 11:35:31 | <solidsnack> | dcoutts: Yes. |
| 11:35:50 | <solidsnack> | dcoutts: I'd like to have a kind of handle that knows whether it's been opened or not. |
| 11:36:14 | <solidsnack> | So I presumably need to do the same hacks that allow a handle to know where it's seeked to. |
| 11:36:28 | <dcoutts_> | solidsnack: that's fine, constructing the handle can be done in IO and can create an IORef, no need for unsafe perform |
| 11:36:52 | <dcoutts_> | solidsnack: similarly, all action on the handle will also be in Io, so no need for unsafe perform |
| 11:37:05 | <solidsnack> | Well, hmmm. |
| 11:40:39 | <solidsnack> | dcoutts: You know, I did not explain myself very well. |
| 11:41:26 | <solidsnack> | Hmm, okay. |
| 11:41:32 | <solidsnack> | I will need to think this over a bit. |
| 11:41:55 | <solidsnack> | There is a really significant difference between constructing a computation that always opens the file and one that may open the file. |
| 11:42:00 | <xenoblitz> | Quick question: Is it ok for me to say: It is important to note that GADTs are still data types and so are first-class objects in Haskell which can be manipulated by the language. Type-classes are not however. |
| 11:42:24 | <solidsnack> | xenoblitz: GADTs are first class objects? |
| 11:43:02 | <xenoblitz> | solidsnack: as in they create items which you can directly manipulate like any data |
| 11:43:25 | <xenoblitz> | solidsnack: I could be wrong I want to see what other people think :) |
| 11:43:57 | <quicksilver> | xenoblitz: yes, a GADT is just another kind of data type. |
| 11:44:09 | <solidsnack> | xenoblitz: I think it's quite reasonable to say they are a datatype. |
| 11:44:26 | <solidsnack> | Whereas typeclasses are not. |
| 11:44:35 | <dcoutts_> | xenoblitz: values are first class, values of a GADT data type are still values. I'm not sure we'd say strictly that types are first class. |
| 11:45:25 | <xenoblitz> | dcoutts: maybe this is better: It is however important to note that GADTs are still data types and so the objects which are created using such types are first-class objects which can be manipulated by the language. Type-classes are not however. |
| 11:45:58 | <dcoutts_> | xenoblitz: yep, though I might switch "object" for "value" |
| 11:46:06 | <dcoutts_> | xenoblitz: object is a loaded term to many readers |
| 11:46:29 | <xenoblitz> | dcoutts: thanks :) |
| 11:57:10 | <Baughn> | @msg conal Congratulations. You've got me obsessively debugging your library just before exams. >_< |
| 11:57:11 | <lambdabot> | Not enough privileges |
| 11:57:19 | <ivanm> | lol |
| 11:57:22 | <Baughn> | @tell conal Congratulations. You've got me obsessively debugging your library just before exams. >_< |
| 11:57:23 | <lambdabot> | Consider it noted. |
| 11:57:32 | <ivanm> | which library is this? reactive? |
| 11:57:39 | <Baughn> | Yes |
| 11:57:49 | <Axman6> | heh |
| 11:58:33 | <ivanm> | ACTION still doesn't get the point of FRP |
| 11:59:45 | <Baughn> | ivanm: It lets you compose your programs by functionally specifying the timelines of whatever objects might be changing. That's rather nice. |
| 11:59:55 | <Baughn> | As far as mutation goes. ;) |
| 11:59:58 | <ivanm> | do you have a concrete example? |
| 12:00:11 | <Baughn> | I wish I did, but no. I keep running into the bugs. |
| 12:00:19 | <ivanm> | see, I get that that's what it does... how it's useful is a different story |
| 12:00:22 | <Baughn> | Once I've fixed those to my satisfaction, I'll get you some. ;) |
| 12:00:30 | <ivanm> | heh |
| 12:00:59 | <Baughn> | ivanm: But basically, if your program requires mutation /anyway/, this is a nicer way to think about it |
| 12:01:02 | <Baughn> | At least for me |
| 12:01:15 | <ivanm> | *nod* |
| 12:01:41 | <ivanm> | is it basically implicitly mapping and discarding an infinite stream of inputs? |
| 12:03:16 | <Baughn> | ivanm: I don't want to answer that. I'm not sure I understand it well enough myself, and it could very easily lead to misunderstandings. |
| 12:03:21 | <ivanm> | *nod* |
| 12:03:33 | <Baughn> | Did you read the paper? |
| 12:03:36 | <ivanm> | that's how I understanding the whole "let's update the evaluation" thing |
| 12:03:37 | <ivanm> | no |
| 12:03:39 | <marcusb> | hi! what's the beginners way to implement a functor for a simple recursive type (arithmetic expressions, lots of operators but simple stuff) without all the boilerplate? |
| 12:03:40 | <ivanm> | which one? :p |
| 12:03:55 | <ivanm> | marcusb: the beginners way is not to do so I believe... ;-) |
| 12:04:01 | <marcusb> | argh :) |
| 12:04:05 | <Baughn> | ivanm: Conal's. |
| 12:04:11 | <marcusb> | what's the advanced beginners way? :) |
| 12:04:14 | <ivanm> | if by "beginners" you mean "beginning haskellers" |
| 12:04:22 | <ivanm> | I've never implemented a functor |
| 12:04:32 | <ivanm> | never really needed to AFAIK |
| 12:05:10 | <Baughn> | marcusb: Thinking.. |
| 12:05:19 | <Baughn> | marcusb: (Well, compiling) |
| 12:05:40 | <mokus> | "beginning haskeller" is a pretty wide stretch of time - I'd say I was a beginning haskeller for almost 2 years, and I'm not a slow learner by any stretch of interpretation |
| 12:06:08 | <Baughn> | marcusb: It's very hard to implement functors automatically, since there are generally a hundred different possible functors for any moderately complex datatype |
| 12:06:29 | <Baughn> | marcusb: Although your own mental model might make only one of them correct, the compiler doesn't know that |
| 12:06:33 | <marcusb> | mokus: okok, what's the easiest way that does not involve me typing the same basic rule "f op a1 a2 = op (f a1) (f a2)" again and again |
| 12:06:43 | <ivanm> | in the sense that I don't go around casually writing new monads all the time, and that I don't use/understand most of the advanced techniques or theory behind them, I am most definitely a beginner haskeller |
| 12:06:59 | <ivanm> | hmmm.... a Haskell Cadet? :p |
| 12:07:01 | <marcusb> | Baughn: well, sure. but "Show" and "Eq" know how to do it |
| 12:07:04 | <solidsnack> | marcusb: It's called sed. |
| 12:07:04 | <marcusb> | for my simple case |
| 12:07:12 | <ivanm> | with SPJ being Lord High Grand Master? :p |
| 12:07:24 | <Baughn> | marcusb: Because those two are much easier to get right. Show and Eq just need to print/compare all the data, respectively. |
| 12:07:46 | <Baughn> | marcusb: However, you might get some use from Scrapping Your Boilerplate. |
| 12:09:07 | <marcusb> | well, maybe my question is really "What's the common idiom". if most users don't use generics for this, but just write it down, maybe I should do that as well |
| 12:09:25 | <Baughn> | marcusb: Speaking for myself, I've never written a Functor complex enough that I cared |
| 12:09:50 | <Baughn> | (So that's one vote for "do it manually") |
| 12:10:06 | <Berengal> | Functor instances are usually just a couple of lines of code anyway |
| 12:10:54 | <quicksilver> | marcusb: uniplate can do that. |
| 12:11:04 | <quicksilver> | marcusb: (automate your functor instance) |
| 12:11:18 | <quicksilver> | Berengal: marcusb's isn't. |
| 12:11:29 | <quicksilver> | Berengal: it's on like per op constructor, and I gather he has lots. |
| 12:11:31 | <doserj> | ghc 6.12 can do it |
| 12:11:52 | <Berengal> | quicksilver: Right... I haven't been paying attention, sorry |
| 12:12:03 | <doserj> | http://hackage.haskell.org/trac/ghc/ticket/2953 |
| 12:12:20 | <marcusb> | quicksilver: realistically, typing it down will be faster than learning the generic modules, but the latter may be more rewarding |
| 12:12:41 | <ivanm> | hmmm.... where people sometimes talk about Monads being containers, isn't it really _Functors_ that are the containers? (or is the container description pre-Functor?) |
| 12:13:12 | <ahamay42> | monads are just special functors, so what's the problem? |
| 12:13:20 | <quicksilver> | ivanm: Yes. |
| 12:13:20 | <Baughn> | Probably that they aren't. ;) |
| 12:13:29 | <Baughn> | ahamay42: They should be, yes |
| 12:13:35 | <quicksilver> | ivanm: Functors are really the contains. Monads are containers in which you can collapse multiple layers. |
| 12:13:42 | <ivanm> | *nod* |
| 12:13:57 | <ivanm> | collapsible containers? for easy storage when you're not using them? |
| 12:14:02 | <dev31212> | Hello, does it take an ungodly amount of time to build the "encoding" module on linux, or is something wrong? |
| 12:14:11 | <dev31212> | it gets stuck on 43 of 47 and has been here for about 30 minutes |
| 12:14:13 | <ivanm> | dev31212: it is long |
| 12:14:17 | <ivanm> | due to too much TH IIRC |
| 12:14:18 | <Berengal> | Of course, saying they're containers isn't the entire truth... |
| 12:14:18 | <Baughn> | quicksilver: And if the monad tutorials explained this, there would be a lot less confusion to go around |
| 12:14:26 | <dev31212> | ah ok ivan |
| 12:14:28 | <dev31212> | thanks |
| 12:14:36 | <dev31212> | so I will let it continue, I guess |
| 12:14:44 | <ivanm> | highlighting-kate also takes forever |
| 12:14:47 | <dev31212> | Also, anyone used Turbinado? |
| 12:14:59 | <dev31212> | hmm highlighting-kate |
| 12:15:26 | <marcusb> | scrap your boilerplate seems to describe my situation |
| 12:16:17 | <quicksilver> | marcusb: Uniplate is something like a simplified SYB |
| 12:16:22 | <quicksilver> | much easier to program with, IMO. |
| 12:16:25 | <quicksilver> | less powerful though. |
| 12:16:37 | <quicksilver> | Baughn: I imagine some of them do. I haven't read many monad tutorials. |
| 12:16:56 | <quicksilver> | I strongly suspect new monad tutorials are being written faster than I can read anyway. |
| 12:17:02 | <Baughn> | quicksilver: I've read a few, but I never saw anything like that before reading the tcopedia |
| 12:17:42 | <marcusb> | I think I only need map's and folds |
| 12:20:38 | <cnwdup> | I load a .hs as a plugin using make and load. If the plugin's module line is "module Name where" all is fine. If I name it "module Plugin.Name where" it fails with unknown symbol "base_GHCziBase_unpackCStringzh_closure." Why is that minor edit causing this? |
| 12:21:04 | <cnwdup> | The Plugins are the following files ./Plugin/Name.hs. So I figured the latter module line was right. |
| 12:21:17 | <quicksilver> | that's very peculiar, cnwdup |
| 12:21:29 | <quicksilver> | I can't explain that error. |
| 12:23:01 | <Jedai> | marcusb: Most usage of generic programming (SYB) could be written without it, but with much more boilerplate, it's up to you to decide if in your case the gain from generic programming would upset the cost of learning a generic library (and I warmly recommend Uniplate too, it's enough for most usage, faster than SYB and easier to learn and use) |
| 12:25:00 | <marcusb> | Jedai: that's great. it's sometimes a bit hard to find the right entry point to a problem solution among all the things that are haskell :) The reason I am looking for this as a beginner is this: After reading the first haskell tutorials, you learn how easy it is to work over lists with map and fold. and then, when you start defining your own types, you lose this elegance. generic programming gives it back. |
| 12:27:08 | <dev31212> | hmm generic programming. |
| 12:27:16 | <dev31212> | Can you provide a link? :) |
| 12:27:30 | <dev31212> | Your description is persuasive. |
| 12:28:22 | <Baughn> | dev31212: Hackage://uniplate and/or scrab your boilerplate |
| 12:28:29 | <quicksilver> | the uniplate paper is a readable place to start |
| 12:28:30 | <Jedai> | dev31212: http://community.haskell.org/~ndm/uniplate/ |
| 12:28:32 | <quicksilver> | IMO. |
| 12:28:36 | <quicksilver> | describes the problem + the solution |
| 12:29:01 | <dev31212> | Thanks |
| 12:32:43 | <PeakerWork> | Baughn: did you manage to debug Reactive a bit? |
| 12:34:21 | <Baughn> | PeakerWork: Not yet. Well, I did manage to switch out TimeT for a fixed-point version, which will come in handy later. |
| 12:34:29 | <Baughn> | PeakerWork: But I've got exams on tuesday, so.. yeah. |
| 12:37:12 | <tomh> | does anyone have experience in using alex tokens with position information in happy? |
| 12:37:42 | <tomh> | more specifically how can i add that position info in my final structure in an elegant way :) |
| 12:41:41 | <frankks> | i'm trying to understand some code, and part of it uses 2 lambdas, does that mean something different? (\\) |
| 12:42:00 | <dev31212> | encoding still hasnt built :( |
| 12:42:28 | <tomh> | frankks: i think thats just divide or something |
| 12:42:34 | <tomh> | @src (\\) |
| 12:42:35 | <lambdabot> | (\\) = foldl (flip delete) |
| 12:42:39 | <tomh> | oh lol |
| 12:42:55 | <vininim> | @src delete |
| 12:42:56 | <lambdabot> | delete = deleteBy (==) |
| 12:43:26 | <vininim> | @src deleteBy |
| 12:43:27 | <lambdabot> | deleteBy eq x [] = [] |
| 12:43:27 | <lambdabot> | deleteBy eq x (y:ys) = if x `eq` y then ys else y : deleteBy eq x ys |
| 12:43:50 | <vininim> | > delete 5 [1..10] |
| 12:43:52 | <lambdabot> | [1,2,3,4,6,7,8,9,10] |
| 12:44:08 | <vininim> | seeing is believing |
| 12:44:47 | <frankks> | @src ($) |
| 12:44:49 | <lambdabot> | f $ x = f x |
| 12:46:07 | <EvilTerran> | > delete 2 [1,2,3,2,1] |
| 12:46:08 | <lambdabot> | [1,3,2,1] |
| 12:46:36 | <dev31212> | > take 2 [1,3,4,6] |
| 12:46:38 | <lambdabot> | [1,3] |
| 12:47:08 | <dev31212> | ( (delete 1).(take 2) ) [1,2,3,4,5,6,7] |
| 12:47:21 | <dev31212> | >( (delete 1).(take 2) ) [1,2,3,4,5,6,7] |
| 12:47:31 | <dev31212> | > ( (delete 1).(take 2) ) [1,2,3,4,5,6,7] |
| 12:47:33 | <lambdabot> | [2] |
| 12:49:39 | <Jedai> | tomh: GHC does that |
| 12:50:30 | <tomh> | mm you know any specific methods or you only are aware that ghc does that? :P |
| 12:52:10 | <dev31212> | Generic seem promising. |
| 12:52:29 | <dev31212> | Though, from a newbs point of view, doesnt this kind of go against the spirit of uber-strong typing? |
| 12:52:46 | <dev31212> | hmm nevermind |
| 12:52:50 | <dev31212> | I guess maybe it doesnt. |
| 12:53:04 | <dev31212> | I think ill pick that back up after I master a few more basics. |
| 12:53:39 | <PeakerWork> | Baughn: exams sound better than deadlines, I guess |
| 12:53:53 | <dev31212> | Hell yes they do. |
| 12:53:59 | <dev31212> | College kids have it easy. |
| 12:54:23 | <dev31212> | As ap rofessional, not only do you have to study more and still have to "cram" |
| 12:54:26 | <EvilTerran> | ACTION has both D: |
| 12:54:35 | <dev31212> | And instead of passing with a C, you get fired for a C |
| 12:55:43 | <dev31212> | makes wish I was a career grade student living on grants |
| 12:59:17 | <bremner> | dev31212: well, feel free to come over to the happy-fun-lazy side :-) |
| 12:59:59 | <dev31212> | heh |
| 13:09:27 | <madhadron> | So, I'm in the process of writing software to control automated microscopes with Haskell... |
| 13:09:40 | <madhadron> | and I realized I was reinventing FRP |
| 13:10:08 | <madhadron> | so does anyone have any wisdom on which of the FRP libraries to use today? |
| 13:13:29 | <Zao> | Elerea seems to be under development at least, no idea of how it compares. |
| 13:14:36 | <madhadron> | It's certainly the smallest and most immediately comprehensible |
| 13:15:23 | <madhadron> | I kind of like reactive's partially push semantics, but probably the time resolution required for microscopy makes that completely irrelevant. |
| 13:15:47 | <quicksilver> | intuitively I prefer reactive, but that may be partly because I understand it better. |
| 13:16:13 | <madhadron> | quicksilver, In that case, can you point me to how to hook it up to IO? |
| 13:16:21 | <pozic> | How can I make a global mutable variable? I can do myGlobal = newIORef 0, but I don't see how I can obtain the actual reference in some unrelated part of the program without reinitalizing the variable every single time. I just want to read it (writing is easy, once you have the ref). |
| 13:16:25 | <madhadron> | I feel like a dunce, but I can't figure out how to generate sources and sinks |
| 13:16:53 | <madhadron> | pozic, Have you looked at MVar? |
| 13:16:57 | <pozic> | I want to use it in code which is not in the IO monad, so I will have to use some unsafePerformIOs in the process. |
| 13:17:11 | <pozic> | madhadron: I don't care about synchronizing variables for this application. |
| 13:17:47 | <madhadron> | pozic, <shrugs> They may be overkill, but they certainly make it easy. |
| 13:18:14 | <quicksilver> | pozic: myGlobal = unsafePerformIO (new IORef 0) |
| 13:18:27 | <quicksilver> | pozic: I won't help you use it though, because I do not understand it |
| 13:18:36 | <dev31212> | Is it common for people to use mutable variables? |
| 13:18:40 | <pozic> | quicksilver: oh, of course. |
| 13:18:51 | <quicksilver> | you need {-# secret GHC pragmas #-} to make it do what you want |
| 13:18:52 | <dev31212> | You gurus, I mean |
| 13:19:07 | <pozic> | quicksilver: I already had that in my file, but forgot for a moment that it wasn't an action anymore at that point ;) |
| 13:19:28 | <quicksilver> | madhadron: No :) I've never used conal's implementation. I have a partial implementation of my own which I know how to hook up to IO ;) |
| 13:19:29 | <pozic> | quicksilver: yes, nobody knows what unsafePerformIO actually does. |
| 13:19:45 | <quicksilver> | actually I know what it does. I just don't know how often GHC will execute it. |
| 13:19:58 | <madhadron> | quicksilver, I see. Ah well. |
| 13:20:12 | <quicksilver> | and having thought about it for a while I am convinced it's the wrong solution, so I haven't spent the time learning the quirks of the optimiser. |
| 13:22:10 | <randomity> | as far as I know, the hack of a module-scope unsafePerformIO'd IOVar is semi-supported, and generally works (although it's never not ugly) |
| 13:22:37 | <randomity> | depending on what you're doing, implicit parameters might solve the problem better than mutable globals, have a look at http://www.haskell.org/ghc/docs/latest/html/users_guide/other-type-extensions.html#implicit-parameters |
| 13:22:48 | <quicksilver> | it's semi-supported insofar as the standard lib uses it. |
| 13:23:01 | <randomity> | (although they might be completely unsuitable, it depends what you're planning with your global) |
| 13:23:09 | <quicksilver> | on the other hand, chunks of the standard lib are written in compiler primitives, so I guess that's not inconsistent. |
| 13:25:55 | <pastorn> | is there a monadic version of mapAccumL? |
| 13:26:10 | <pastorn> | or do i need to write it myself? |
| 13:26:11 | <quicksilver> | mapM in StateT over the monad you first thought of? |
| 13:27:07 | <pastorn> | quicksilver: our monad is already an instance of MonadState, so that'd probably make things go south |
| 13:27:30 | <quicksilver> | it wouldn't make things go south, no. |
| 13:27:43 | <quicksilver> | it just means you'd need to be careful |
| 13:31:10 | <madhadron> | Aha. I found how to hook Conal's reactive to IO... |
| 13:31:54 | <quicksilver> | yay :) |
| 13:31:55 | <madhadron> | Hidden down in FRP.Reactive.LegacyAdapters, there's a makeEvent which hands back a sink and an event. |
| 13:33:06 | <madhadron> | So you makeClock, then pass that to a bunch of makeEvents, which you then proceed to hook up as callbacks from whatever's coming in from outside. |
| 13:33:29 | <madhadron> | What confused me is that the type shown in the Haddock docs looks mangled |
| 13:33:41 | <madhadron> | makeEvent :: Clock TimeT -> a :+-> Event a |
| 13:34:38 | <quicksilver> | a :+-> b is a type constructor meaning (a -> IO (), b), IIRC |
| 13:34:48 | <quicksilver> | I.e. Sink a, b |
| 13:34:55 | <madhadron> | Aha. No wonder I was confused. |
| 13:35:24 | <madhadron> | Is that defined in reactive, or off in the core somewhere? |
| 13:36:28 | <quicksilver> | reactive somewhere |
| 13:36:56 | <madhadron> | Thanks. |
| 15:01:59 | <fasta> | Is there a parallel version of mapM? |
| 15:03:41 | <doserj> | sequence . parMap strat f? |
| 15:04:50 | <fasta> | doserj: I doubt that will work. That will only evaluate the actions in parallel, not execute them in parallel. |
| 15:06:17 | <doserj> | yeah. but a parallel sequence isn't really possible, is it? |
| 15:06:28 | <Saizan> | why not? |
| 15:06:47 | <Saizan> | fasta: there's a lib on hackage iirc |
| 15:07:59 | <Saizan> | i don't recall the name though.. |
| 15:08:14 | <mmorrow> | fasta: that reminds me of an old paste, not exactly what you're after, but related. maybe it'd be useful (note: i don't recall if i tested this) http://moonpatio.com/fastcgi/hpaste.fcgi/view?id=828 |
| 15:08:49 | <gnuvince> | Could anyone look at this and tell me if there's a nicer way to write the last parameter of loop? http://www.moonpatio.com/fastcgi/hpaste.fcgi/view?id=2453#a2453 |
| 15:09:00 | <quicksilver> | there was something called nMergeIO or somethign, wasn't there? |
| 15:09:05 | <quicksilver> | @hoogle nmergeio |
| 15:09:06 | <lambdabot> | Control.Concurrent nmergeIO :: [[a]] -> IO [a] |
| 15:09:06 | <mmorrow> | (it really should be called parSequence_ i guess. it ensures that only N threads are running at a time) |
| 15:09:18 | <quicksilver> | hmm I'm not sure that's what I wanted though :) |
| 15:09:38 | <mmorrow> | whoa, didn't know about nmergeIO |
| 15:09:38 | <fasta> | mmorrow: yes, the worker threads thing. That's also something I wrote before. This time, however I don't want to have IO. |
| 15:09:51 | <mmorrow> | fasta: ah, interesting. hmm |
| 15:10:18 | <fasta> | Why does nmergeIO have IO in its return type? |
| 15:11:36 | <mmorrow> | i guess it probably returns results as they finish |
| 15:12:27 | <mmorrow> | (finish evaluating or something) |
| 15:12:35 | <mmorrow> | ACTION looks for the code of nmergeIO |
| 15:15:22 | <fasta> | It's sort of the analog of + having the type Int -> Int -> IO Int |
| 15:16:16 | <mmorrow> | i think though that the order of elems in the result list is nondeterministic |
| 15:16:24 | <mmorrow> | ah, found the code |
| 15:16:25 | <mmorrow> | ACTION pastes |
| 15:17:52 | <mmorrow> | fasta, quicksilver: nmergeIO: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5075#a5075 |
| 15:19:10 | <Axman6> | how cool, seems i'll be learning Ada next semester |
| 15:20:28 | <Raevel> | there's a new ada course at my school, you write a simulator for a rally car driver in the western part of sweden |
| 15:20:37 | <Raevel> | or so i've heard |
| 15:20:41 | <quicksilver> | that's very specific. |
| 15:20:51 | <mmorrow> | heh |
| 15:20:59 | <qaz> | > let (->) a b = a+b in (->) 10 20 |
| 15:21:00 | <lambdabot> | <no location info>: parse error on input `->' |
| 15:21:01 | <quicksilver> | is a simulator for a rally car driver in northern spain, say, a very different thing? |
| 15:21:10 | <qaz> | > let (_>) a b = a+b in (_>) 10 20 |
| 15:21:11 | <lambdabot> | <no location info>: Parse error in pattern |
| 15:21:22 | <doserj> | quicksilver: in winter, yes |
| 15:21:31 | <mmorrow> | quicksilver: you probably have to simulate the soil composition differently or something :P |
| 15:21:37 | <quicksilver> | ah yes |
| 15:21:48 | <quicksilver> | I always forget to correctly account for soil composition, in my rally simulators |
| 15:21:54 | <Baughn> | quicksilver: It's sweden, so you only need to draw trees on every side of the road |
| 15:22:00 | <quicksilver> | the migration routes of birds often catches me out too. |
| 15:22:00 | <mmorrow> | it's one of those "gotchas" for sure |
| 15:22:09 | <mmorrow> | ooh, true |
| 15:22:18 | <Axman6> | also, Ada needs to know what soil it will be simulating at compiloe time |
| 15:22:25 | <Axman6> | or it will throw an error |
| 15:23:07 | <Axman6> | type Soil is sandy loam; |
| 15:23:09 | <fasta> | If there are no performance criteria, there is a very nice solution you can use. |
| 15:23:18 | <gnuvince> | Could anyone look at this and tell me if there's a nicer way to write the last parameter of loop? http://www.moonpatio.com/fastcgi/hpaste.fcgi/view?id=2453#a2453 |
| 15:24:07 | <fasta> | You can use a similar argument for every data structures course that has questions of the form given an outline of an algorithm which runs in O(f(n)) time (where they leave out that it must have a practical constant). |
| 15:26:11 | <fasta> | give* |
| 15:29:06 | <qaz> | > let (_) a b = a+b in (_) 10 20 |
| 15:29:07 | <lambdabot> | <no location info>: Parse error in pattern |
| 15:29:16 | <qaz> | > let f a b = a+b in f 10 20 |
| 15:29:19 | <lambdabot> | 30 |
| 15:29:33 | <qaz> | > let (*****) a b = a+b in (*****) 10 20 |
| 15:29:35 | <lambdabot> | 30 |
| 15:29:49 | <qaz> | > let (*+) a b = a+b in (*+) 10 20 |
| 15:29:51 | <vininim> | > let (._.) a b = a*b in 10 ._. 20 |
| 15:29:51 | <lambdabot> | 30 |
| 15:29:52 | <lambdabot> | <no location info>: parse error on input `)' |
| 15:29:57 | <qaz> | > let (*+) a b = a+b in (*+) 10 20 |
| 15:29:59 | <lambdabot> | 30 |
| 15:32:54 | <Axman6> | wow... Ada is confusing |
| 15:34:47 | <quicksilver> | qaz: lambdabot responds to private messages. |
| 15:38:20 | <pe> | Hi. Is there a way to declare IO things instances of Show ? i.e. instance Show IORef where ... ? |
| 15:38:22 | <roadwarrior> | can one downgrade ghc to 6.8 after installing the latest haskellPlatform on windows? |
| 15:38:31 | <mmorrow> | fasta: maybe something like this? http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5075#a5076 |
| 15:38:42 | <Zao> | roadwarrior: Nothing stops you from having more than one GHC on the system. |
| 15:38:49 | <quicksilver> | pe: nothing stops you making IORef an instance of Show, but it may be quite hard to make it a useful instance. |
| 15:39:07 | <quicksilver> | pe: instance Show (IORef a) where show r = "<IORef>" |
| 15:39:10 | <quicksilver> | pe: for example... |
| 15:39:11 | <Zao> | roadwarrior: Installed libraries are tied to the GHC version used though, so you'd get (sane) multiple installs when reinstalling a library. |
| 15:39:23 | <quicksilver> | would be a valid, if not terribly useful, instance. |
| 15:39:31 | <mmorrow> | fasta: (where the sort's useless unless one cares about deterministic results) |
| 15:39:48 | <pe> | quicksilver : right, ok :-) |
| 15:39:59 | <roadwarrior> | Zao: ok, thats what I wanted to know. So it binds to the correct version. |
| 15:40:00 | <roadwarrior> | thanks |
| 15:40:26 | <quicksilver> | pe: you could imagine an instance which at least showed some underlying unique ID (perhaps even a memory pointer) for the purposes of telling them apart. |
| 15:40:40 | <quicksilver> | pe: but, you'd need access to the internals of the implementation to do that :( |
| 15:41:18 | <Zao> | roadwarrior: Whichever one is found as "ghc" is the one first in the path. |
| 15:41:19 | <mmorrow> | fasta: personally, i'd just skip the sort, since then it'd work on infinite lists (but not be deterministic of course) |
| 15:41:27 | <pe> | quicksilver : I'm doing a C binding, I have a CString in a struct, and I'd just like to be able to print myStruct |
| 15:41:37 | <Zao> | I believe you can invoke them as ghc-6.8.3 if you want a particular one. |
| 15:41:42 | <quicksilver> | @hoogle CString |
| 15:41:42 | <lambdabot> | Foreign.C.String type CString = Ptr CChar |
| 15:41:42 | <lambdabot> | Foreign.C.String type CStringLen = (Ptr CChar, Int) |
| 15:41:42 | <lambdabot> | Foreign.C.String newCString :: String -> IO CString |
| 15:41:47 | <Zao> | Or just not put them in path and point them out when you need them. |
| 15:42:05 | <fasta> | mmorrow: my problem was a parallel mapM where the order of the effects is not important, as long as they happen. |
| 15:42:10 | <quicksilver> | pe: well the cleanest thing to is to have a haskell-version of the data structure which actually contains the string |
| 15:42:14 | <quicksilver> | pe: not just a Ptr... |
| 15:42:14 | <fasta> | mmorrow: but this is nice too. |
| 15:42:19 | <mmorrow> | fasta: ah, right. hmm |
| 15:42:26 | <pe> | quicksilver : ok, thanks |
| 15:42:36 | <mmorrow> | fasta: yeah, /me adds nmerge to his library |
| 15:43:06 | <roadwarrior> | Zao: Ok |
| 15:44:01 | <fasta> | mmorrow: what's the point of the [[a]] in the type of nmergeIO btw? |
| 15:44:12 | <fasta> | mmorrow: is every list for one core? |
| 15:44:25 | <fasta> | mmorrow: or thread/whatever |
| 15:44:55 | <mmorrow> | i'm not sure, i didn't look at the code that closely |
| 15:44:57 | <mmorrow> | ACTION looks |
| 15:45:17 | <mmorrow> | ah |
| 15:45:19 | <mmorrow> | -- The 'mergeIO' and 'nmergeIO' functions fork one thread for each |
| 15:45:19 | <mmorrow> | -- input list that concurrently evaluates that list; |
| 15:50:52 | <fasta> | mmorrow: yes, that's what I expected. |
| 15:52:22 | <quicksilver> | pe: if you dont' much care, you could unsafePerformIO the Ptr read |
| 15:52:55 | <mmorrow> | instance (Show a) => Show (IORef a) where show ref = unsafePerformIO (show `fmap` readIORef a) |
| 15:53:02 | <mmorrow> | oop |
| 15:53:02 | <pe> | that's an idea. In fact in a C binding ... |
| 15:53:03 | <mmorrow> | oo |
| 15:53:06 | <mmorrow> | instance (Show a) => Show (IORef a) where show ref = unsafePerformIO (show `fmap` readIORef ref) |
| 15:53:10 | <pumpkin> | lol |
| 15:53:15 | <mmorrow> | s/oo/s/ |
| 15:53:37 | <mmorrow> | , [|\x->x|] |
| 15:53:41 | <lunabot> | LamE [VarP x_0] (VarE x_0) |
| 15:53:54 | <mmorrow> | instance Show ExpQ where show = unsafePerformIO . runQ |
| 15:54:03 | <mmorrow> | instance Show ExpQ where show = show . unsafePerformIO . runQ |
| 15:54:05 | <mmorrow> | i mean |
| 15:55:18 | <mmorrow> | (which makes it essentially to hide (runIO :: IO a -> Q a) in teh bot) |
| 15:57:05 | <mmorrow> | pumpkin: so you've got a booted ghc for osx x86_64? |
| 15:57:15 | <pumpkin> | yeah, but it's not usable right now |
| 15:57:26 | <mmorrow> | aww, what's the breakage? |
| 15:57:28 | <pumpkin> | you have to link the .o files by hand |
| 15:57:35 | <pumpkin> | I did it a few times but it's a pain |
| 15:57:37 | <mmorrow> | ah |
| 15:57:59 | <pumpkin> | it's a pretty easy fix from there though |
| 15:58:08 | <pumpkin> | I just forgot to add some parameters to the driver |
| 15:58:10 | <mmorrow> | pumpkin: iirc ghc calls ld from compiler/main/{DriverPipeline,SysTools}.lhs |
| 15:58:16 | <pumpkin> | yup |
| 15:58:30 | <pumpkin> | I added suitable parameters to the cc and as steps of DriverPipeline, but forgot ld :) |
| 15:58:34 | <mmorrow> | heh |
| 15:58:37 | <mmorrow> | "doh!" |
| 15:58:46 | <pumpkin> | and was too lazy to wait for it again |
| 15:58:46 | <pumpkin> | :P |
| 15:59:20 | <mmorrow> | if you do edit that again, it might be nice if those mods didn't have hardcoded options for the various progs.. |
| 16:00:00 | <mmorrow> | or at least, just as the fallback if no over-ride flags are provided (somehow) |
| 16:00:16 | <pumpkin> | well, they're represented as preprocessor conditionals on the target |
| 16:00:31 | <pumpkin> | so they only add the flags in if you're compiling for mac os x and x6_64 |
| 16:00:33 | <pumpkin> | x86_64 |
| 16:00:40 | <mmorrow> | pumpkin: yeah, i mean keep those, but add the ability to override the defaults |
| 16:00:46 | <pumpkin> | ah |
| 16:01:07 | <mmorrow> | (you'd have to workout some way to specify overrides though..) |
| 16:01:17 | <pumpkin> | yeah, makes sense |
| 16:01:18 | <mmorrow> | which may or may not turn into an epic |
| 16:02:39 | <pumpkin> | :) |
| 16:02:46 | <pumpkin> | I need to shower and go out! I'll be back |
| 16:08:00 | <lilac> | @hoogle pipe |
| 16:08:00 | <lambdabot> | package Pipe |
| 16:08:01 | <lambdabot> | package shell-pipe |
| 16:11:09 | <lysgaard> | How do i make my own typeclass for the (^) |
| 16:11:20 | <lysgaard> | \:t (^) |
| 16:11:33 | <quicksilver> | well, the built-in (^) uses Num and Integral |
| 16:11:36 | <quicksilver> | nothing you can do abotu that |
| 16:11:48 | <quicksilver> | you can write your own function called (^) and make it do whaetver you want, of course |
| 16:12:03 | <pumpkin> | you can also write an instance that can be a base, or an exponent of (^) |
| 16:12:47 | <lysgaard> | Yeah, that's what i'm after. I have my own datatype and i want (^) te behave in a special way on it |
| 16:13:17 | <lilac> | how can i call pipe(2) from Haskell? do i have to FFI it or is it already available somewhere? |
| 16:13:34 | <pumpkin> | lysgaard: write a Num instance if you want your type to be the base, or an integral instance if you want it to be the exponent |
| 16:14:10 | <lysgaard> | pumpkin: What if i want it to be in both? |
| 16:14:23 | <quicksilver> | lilac: does anything in System.Process do what you want? |
| 16:14:25 | <pumpkin> | integral is both, but in that case you probably don't want (^) |
| 16:14:32 | <pumpkin> | :t (**) |
| 16:14:34 | <pumpkin> | :t (^^) |
| 16:14:34 | <lambdabot> | forall a. (Floating a) => a -> a -> a |
| 16:14:35 | <lambdabot> | forall a b. (Integral b, Fractional a) => a -> b -> a |
| 16:14:50 | <quicksilver> | lilac: what do you want to do with the pipe once you've made it, in other words? |
| 16:14:57 | <quicksilver> | pumpkin: well (^) isn't a method, it's a function. |
| 16:15:02 | <quicksilver> | its semantics are fixed. |
| 16:15:05 | <pumpkin> | I know |
| 16:15:09 | <quicksilver> | it always works by repeated squaring. |
| 16:15:17 | <pumpkin> | yeah |
| 16:15:24 | <quicksilver> | so you can't make your type do anything other than repeated squaring. |
| 16:15:39 | <lysgaard> | Hm, ok, but i just need a method i can make an instance of |
| 16:15:45 | <pumpkin> | I never implied otherwise, did I? :o |
| 16:15:58 | <lilac> | quicksilver: i'm trying to implement unsafeInterleaveIO in terms of lazy IO ;-) |
| 16:16:15 | <lysgaard> | So (^) won't cut it. What are my options then? |
| 16:17:04 | <lysgaard> | pumpkin: Can i use any of (**) (^^) ? |
| 16:17:15 | <pumpkin> | @src Fractional |
| 16:17:15 | <lambdabot> | class (Num a) => Fractional a where |
| 16:17:15 | <lambdabot> | (/) :: a -> a -> a |
| 16:17:15 | <lambdabot> | recip :: a -> a |
| 16:17:15 | <lambdabot> | fromRational :: Rational -> a |
| 16:17:18 | <pumpkin> | @src Floating |
| 16:17:19 | <lambdabot> | class (Fractional a) => Floating a where |
| 16:17:19 | <lambdabot> | pi :: a |
| 16:17:21 | <lambdabot> | exp, log, sqrt, sin, cos, tan :: a -> a |
| 16:17:23 | <lambdabot> | asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh :: a -> a |
| 16:17:25 | <lambdabot> | (**), logBase :: a -> a -> a |
| 16:17:31 | <quicksilver> | lysgaard: what are you actually trying to do? |
| 16:17:44 | <quicksilver> | pumpkin: that's really spammy :P |
| 16:17:52 | <pumpkin> | sorry :( |
| 16:18:04 | <dev31212> | Say, if I know the name of a module...in this case "Config.Database" what is the easiest way to find out what package I need to install? |
| 16:18:06 | <quicksilver> | lilac: lol. |
| 16:18:23 | <quicksilver> | lilac: maybe it's FFIed already by somethign in System.Posix? |
| 16:18:37 | <quicksilver> | @hoogle Config.Database |
| 16:18:38 | <lambdabot> | No results found |
| 16:18:46 | <quicksilver> | dev31212: try searching on hoogle or hayoo |
| 16:18:53 | <dev31212> | oh thats what hayoo is |
| 16:18:55 | <dev31212> | gotcha |
| 16:18:58 | <dev31212> | thanks quicksilver |
| 16:19:23 | <quicksilver> | hmm. |
| 16:19:27 | <quicksilver> | neither of them finds it, though. |
| 16:19:28 | <lysgaard> | pumpkin: I'm making a symbolic math type, and now i want to implement the raise to function: http://hpaste.org/fastcgi/hpaste.fcgi/save |
| 16:19:43 | <pumpkin> | um |
| 16:19:45 | <quicksilver> | lysgaard: I would just give it a new name. |
| 16:20:00 | <quicksilver> | > a ^ 5 |
| 16:20:02 | <lambdabot> | a * a * (a * a) * a |
| 16:20:08 | <quicksilver> | is repeated squaring so bad? ;) |
| 16:20:25 | <pumpkin> | it can't show sharing :/ |
| 16:20:33 | <pumpkin> | the simple-reflect |
| 16:20:41 | <lysgaard> | Well, cant use it for (a + 1)^(a - 4) |
| 16:20:50 | <quicksilver> | lysgaard: ah, indeed you can't :) |
| 16:21:10 | <quicksilver> | lysgaard: I think you're best of giving it a new name. |
| 16:21:30 | <lysgaard> | So, should i just make a new function, that does my type of squaring |
| 16:28:56 | <leimy> | dons: around? |
| 16:30:12 | <lilac> | quicksilver: hooray, System.Posix.IO.createPipe :) |
| 16:30:30 | <leimy> | @seen dons |
| 16:30:30 | <lambdabot> | dons is in #haskell-in-depth, #concatenative, #arch-haskell, #darcs, #yi, #xmonad, #ghc and #haskell. I last heard dons speak 1h 4m 55s ago. |
| 16:30:40 | <quicksilver> | lilac: ;) |
| 16:30:54 | <leimy> | found a bug in ByteString.CSV :-) |
| 16:34:05 | <dev31212> | ahhh I found out what I did wrong :p |
| 16:34:09 | <dev31212> | silly mistake... |
| 16:34:22 | <dev31212> | evidently with Trubinado it is up to YOU to provide the Confid.Database... |
| 16:34:49 | <mmorrow> | lilac: i've got some code that ffi imprts pipe (among other things) at the bottom of http://moonpatio.com/repos/vacuum-gl/System/Vacuum/OpenGL/MMGV.hs |
| 16:34:53 | <dev31212> | turbinado*,Config.Database* |
| 16:35:30 | <quicksilver> | dev31212: Aha! :) |
| 16:36:07 | <mmorrow> | lilac: (and has a minimal wrapper for (c_pipe :: Ptr CInt -> IO ()) ==> (pipe :: IO (CInt, CInt)) that brackets (mallocArray 2) free |
| 16:39:37 | <mmorrow> | lilac: actually, this code is better. it has the same pipe wrapper code/etc as the one i just linked to, but also ffi imports select (stolen (and de-underscored ;) from oleg's zfs code) http://moonpatio.com/repos/lunabot/Dup.hs |
| 16:39:57 | <mmorrow> | selectR :: [CInt] -> IO [CInt] |
| 16:40:21 | <mmorrow> | oleg was also having the select call block, this one passes in a 0 timeout |
| 16:40:39 | <lament> | conal: nice post on purity of c |
| 16:40:40 | <mmorrow> | (i.e. don't block at all) |
| 16:40:49 | <lament> | conal: i always felt this way but was unable to express it :) |
| 16:41:03 | <eu-prleu-peupeu> | conal elliot last post is cool |
| 16:41:10 | <leimy> | hehe yeah |
| 16:41:16 | <leimy> | C++ is pure too |
| 16:41:19 | <leimy> | if you just count templates :-) |
| 16:42:31 | <conal> | lament: :) thanks! |
| 16:42:31 | <lambdabot> | conal: You have 2 new messages. '/msg lambdabot @messages' to read them. |
| 16:42:35 | <leimy> | But really, isn't everything doing a form of I/O to memory and registers? |
| 16:42:38 | <conal> | eu-prleu-peupeu: thanks! |
| 16:42:39 | <leimy> | even if really really pure? |
| 16:42:44 | <leimy> | something is doing "I/O" at some point :-) |
| 16:42:47 | <conal> | and two "t"s in Elliott, please! |
| 16:42:48 | <lament> | leimy: then what does "really really pure" mean? |
| 16:42:54 | <leimy> | exactly |
| 16:42:59 | <leimy> | it boils down to "pure enough" |
| 16:43:02 | <leimy> | followed by "who cares?" |
| 16:43:11 | <leimy> | and lastly, if you want to be rude "now stfu!" :-) |
| 16:44:06 | <leimy> | ACTION is trying to figure out if he should attempt to fix dons's CSV parser.... or if he should just live with the limitations. |
| 16:44:21 | <conal> | there. i just posted a couple of replies at http://conal.net/blog/posts/the-c-language-is-purely-functional |
| 16:44:29 | <pumpkin> | zomg heresy :) |
| 16:44:45 | <leimy> | pumpkin: heresy? |
| 16:44:52 | <leimy> | He's got TODO's in his code :-) |
| 16:44:58 | <Badger> | ACTION thinks asm is purely functional |
| 16:45:01 | <pumpkin> | was taking about conal's heretical post :) |
| 16:45:05 | <leimy> | oh |
| 16:45:08 | <mmorrow> | conal: "When a C practitioner suddenly groks the purely functional monadic essence of their tool, the force of shock is so great that it may catapult him/her into enlightenment." |
| 16:45:17 | <mmorrow> | conal: elegant statement |
| 16:45:24 | <conal> | :) |
| 16:45:55 | <leimy> | conal: are you a Seattlite? |
| 16:46:01 | <conal> | leimy: yes, a functional language's run-time system is extremely stateful (I/O to registers etc). |
| 16:46:15 | <leimy> | makes sense |
| 16:46:24 | <Saizan> | conal: the monad analogy doesn't quite hold, since CPP macros can't create new C values at runtime |
| 16:46:26 | <conal> | leimy: i lived in seattle for 13 years. moved to the woods in california two years ago. |
| 16:46:26 | <leimy> | Some cool pics of lightning hitting the space needle last night |
| 16:46:32 | <leimy> | conal: ah... |
| 16:46:36 | <conal> | Saizan: yeah, you're right. |
| 16:46:41 | <pumpkin> | conal: so you're 15? |
| 16:46:42 | <conal> | Saizan: it's really a monoid |
| 16:46:49 | <leimy> | http://www.komonews.com/news/local/45457632.html |
| 16:47:06 | <lilac> | mmorrow: the wrapper in System.Posix.IO is plenty good enough for my purposes |
| 16:47:14 | <conal> | pumpkin: no one said there'd be math. :) |
| 16:47:36 | <conal> | leimy: yow! |
| 16:47:36 | <lilac> | quicksilver: i have 'deferIO :: IO () -> IO DeferredIO' and 'performDeferredIO :: DeferredIO -> ()' working ;-) |
| 16:47:52 | <lilac> | am i supposed to be able to do that without unsafe*? |
| 16:47:59 | <leimy> | conal: it was pretty impressive here yesterday :-) |
| 16:47:59 | <mmorrow> | i'm constantly annoyed that CPP isn't more powerful.. i.e. it's just simple substitution rather than substituting the result of evaluating an expression |
| 16:48:35 | <conal> | hm. Firefox just garbage-collected |
| 16:48:40 | <conal> | (i.e., crashed) |
| 16:48:40 | <mmorrow> | , listE (repliclate 20 [|()|]) |
| 16:48:41 | <lunabot> | luna: Not in scope: `repliclate' |
| 16:48:45 | <mmorrow> | , listE (replicate 20 [|()|]) |
| 16:48:47 | <lunabot> | ListE [ConE (),ConE (),ConE (),ConE (),ConE (),ConE (),ConE (),ConE (),Co... |
| 16:48:53 | <mmorrow> | , ppDoc `fmap` listE (replicate 20 [|()|]) |
| 16:48:54 | <lunabot> | [(), |
| 16:48:54 | <lunabot> | (), |
| 16:48:54 | <lunabot> | (), |
| 16:49:01 | <roconnor> | I've been trying to find a way to explain/convey the difference between programming "inside a monad" and "outside a monad". |
| 16:49:11 | <pumpkin> | yay, it's codolio |
| 16:49:15 | <mmorrow> | ppDoc `fmap` listE (replicate 2000 [|()|]) |
| 16:49:19 | <lilac> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5078#a5078 |
| 16:49:31 | <roconnor> | Because programming in the list monad is "non-deterministic", but, of course, haskell is deterministic. |
| 16:49:42 | <lilac> | ^^ defer performing any IO computation until a pure value is forced |
| 16:49:49 | <lilac> | ACTION feels dirty |
| 16:50:17 | <mmorrow> | lilac: why dirty? |
| 16:50:25 | <lilac> | mmorrow: my pure code has side effects |
| 16:50:32 | <lilac> | and i didn't use unsafe* |
| 16:50:36 | <mmorrow> | so? :) |
| 16:51:04 | <conal> | Saizan: i'll post the monad/monoid correction on my blog. |
| 16:51:12 | <roconnor> | It's not just IO programing that is impure, but any monadic programming is typically impure. |
| 16:51:39 | <roconnor> | I think is it that we are implicitly programming with Kleisli arrows when doing monadic programming. |
| 16:52:08 | <pumpkin> | :o |
| 16:52:10 | <gnuvince> | Is there a way to make this code less messy: ((digits !! fromInteger (y `mod` radix)):acc) |
| 16:52:12 | <roconnor> | anyhow, I'm still lacking the proper language to explain this difference well. |
| 16:52:38 | <conal> | roconnor: in that we usually work with 'a -> m b', not just 'm b'? |
| 16:52:47 | <roconnor> | @type Numeric.showIntAtBase |
| 16:52:48 | <lambdabot> | forall a. (Integral a) => a -> (Int -> Char) -> a -> String -> String |
| 16:52:53 | <roconnor> | gnuvince: ^^ |
| 16:53:21 | <roconnor> | conal: not only work with, but think of it that way too. |
| 16:53:37 | <Twey> | showIntAtBase radix (digits !!) y "" |
| 16:54:06 | <gnuvince> | > showIntAtBase 2 ("0123"!!) 10 "" |
| 16:54:07 | <lambdabot> | "1010" |
| 16:54:11 | <gnuvince> | nifty |
| 16:54:24 | <mmorrow> | haha, void firefox_gc(void){abort();} |
| 16:54:29 | <ski> | (roconnor : i agree ..) |
| 16:55:12 | <ski> | roconnor : basically, we're thinking in the Kleisli category, when thinking "in the monad" |
| 16:55:33 | <ski> | which is just what effectful programming is about |
| 16:55:47 | <roconnor> | When I'm programming "in a monad" I'm thinking that I have state, and I'm not deterministic, but when I step back, I see that I'm doing backtracking search and composing state transformers. |
| 16:55:51 | <roconnor> | @quote MonadState |
| 16:55:52 | <lambdabot> | MonadState says: Do not try to change the state; that's impossible. Instead only try to realize the truth: There is no state. |
| 16:56:00 | <ski> | (or at least one useful formalization of "effectful") |
| 16:56:38 | <roconnor> | ski: trying to convey this in a talk is difficult. |
| 16:57:19 | <ski> | roconnor : in that case, the difference is only in the frame of mind .. if haskell had syntax for monadic reflection, it would be a difference in syntax as well (i suppose this sounds trivial now when i state it) |
| 16:58:02 | <ski> | the direct side-effectful syntax of typical (and not-so-typical) imperative languages is more or less a convenience, methinks |
| 16:58:06 | <roconnor> | ski: particularly strange how you are working in this beautiful pure world, and it has this strange IO box. But when you step into that box, and look back you see that you are in the real world, and that pure world isn't. It is just a box in the real world with wires and stuff. |
| 16:58:30 | <EvilTerran> | roconnor, how poetic |
| 16:58:41 | <dev31212> | ok, here is what I learned |
| 16:58:46 | <dev31212> | because this room is so helpful |
| 16:59:04 | <dev31212> | If you try out turbinado, dont do the "git" as it says on the website... |
| 16:59:09 | <dev31212> | do it like this : git clone git://github.com/alsonkemp/turbinado-website.git |
| 16:59:36 | <ski> | roconnor : one could use this as a rationale for an operation that in the outside environment prints the n decimals that has been found for an internal pure computation of a computable real |
| 16:59:48 | <roconnor> | I was about to suggest dev31212 put that up on the wiki, but I don't know how painful it is to get an account now. |
| 16:59:53 | <pumpkin> | dev31212: might it not be better to warn the developer? |
| 17:00:00 | <dev31212> | pumpkin, good idea |
| 17:00:03 | <dev31212> | ill do that now |
| 17:00:07 | <pumpkin> | :) |
| 17:00:13 | <lilac> | conal: i can create (inside the IO monad, without using unsafe*) a pure value, which, when forced, has arbitrary side-effects. horrified? |
| 17:00:17 | <ski> | roconnor : inside the pure computation, we can't depend on decimal representation .. but outside, we can set time limits and gather the decimals so far .. |
| 17:00:52 | <lilac> | conal: also, i loved your 'C as a pure language' blog post :) |
| 17:00:57 | <roconnor> | lilac: you can? |
| 17:01:12 | <conal> | Saizan: i'm adding a blog comment quoting and responding to your not-a-monad remark. would you rather i didn't refer to you by your real name (in addition to irc handle)? |
| 17:01:20 | <mmorrow> | lilac: if that's what the situation calls for, then i see it as haskell not being expressive/whatever enough for the problem at hand, rather that a failure on your part. |
| 17:01:28 | <conal> | lilac: :D |
| 17:01:30 | <SamB> | lilac: how? |
| 17:01:31 | <ik> | lilac: link? |
| 17:01:46 | <roconnor> | lilac: lambdabot or it didn't happen. :P |
| 17:01:57 | <lilac> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5078#a5078 |
| 17:02:00 | <lilac> | ^^ like that |
| 17:02:15 | <lament> | is vim usable for haskell these days? |
| 17:02:20 | <ski> | roconnor : btw, even though it's often better to avoid using effectful computations, i think effectful computations are sometimes warranted precisely because they can improve the modularity and robustness of code |
| 17:02:29 | <EvilTerran> | lilac, ah, because hGetContents uses unsafeInterleaveIO internally |
| 17:02:35 | <lilac> | EvilTerran: right :) |
| 17:02:38 | <magical_pony> | vim's highly usable for haskell. |
| 17:02:55 | <pumpkin> | > ((thrice . thrice) (+1)) 0 |
| 17:02:56 | <lambdabot> | 9 |
| 17:03:02 | <pumpkin> | > ((thrice thrice) (+1)) 0 |
| 17:03:03 | <lambdabot> | 27 |
| 17:03:04 | <mux> | I've always used vim for haskell coding |
| 17:03:05 | <lilac> | it's easy to extend it to allow the IO action to produce a string |
| 17:03:20 | <lilac> | but arbitrary return values are harder (perhaps impossible?) |
| 17:03:23 | <lament> | does it handle indentation nicely? |
| 17:03:23 | <EvilTerran> | > thrice thrice thrice (+1) 0 |
| 17:03:25 | <lambdabot> | * Exception: stack overflow |
| 17:03:34 | <EvilTerran> | uh |
| 17:03:42 | <Twey> | emacs is even more usable for Haskell. |
| 17:03:44 | <lament> | does it have something like the emacs thing where Tab cycles through possible indentations? |
| 17:03:50 | <magical_pony> | i believe so. |
| 17:03:53 | <magical_pony> | inb4 editor war |
| 17:04:49 | <mux> | lament: vim can do this since vim 7, using the ^N key combination |
| 17:05:18 | <Twey> | How do you get vim to show the type of an expression under the cursor? |
| 17:05:42 | <magical_pony> | ...you look at it's type signature? :P |
| 17:05:46 | <mux> | there is a vim script floating around for that |
| 17:06:05 | <roconnor> | I don't get the hGetContents problem |
| 17:06:33 | <lament> | Twey: i've seen that thing somewhere |
| 17:06:49 | <BONUS> | roconnor: you mean why some consider it bad? |
| 17:06:50 | <conal> | i just replied to Saizan's C-as-monad objection: http://conal.net/blog/posts/the-c-language-is-purely-functional |
| 17:07:17 | <mux> | http://www.cs.kent.ac.uk/people/staff/cr3/toolbox/haskell/Vim/ |
| 17:08:10 | <roconnor> | BONUS: I don't understand what property people claims it breaks. |
| 17:08:55 | <BONUS> | purity. because you can have an expression whose value depends on when it's evaluated |
| 17:09:11 | <BONUS> | if something is pure, it shouldn't matter if you evaluate it now or later |
| 17:09:32 | <BONUS> | but when you do x <- hGetContents someHandle |
| 17:09:49 | <BONUS> | when the file is read depends on when x is evaluated |
| 17:09:54 | <BONUS> | even though x should be pure |
| 17:10:00 | <ski> | afaiu it technically is pure .. up to `IO' being blamed for nondeterminism |
| 17:10:18 | <lilac> | haha, i've got a pure value which, when forced, reads a string from the keyboard |
| 17:10:27 | <lilac> | (and returns it) |
| 17:11:27 | <lilac> | now all i need is an infinite list of these and i can implement unsafePerformIO |
| 17:11:31 | <mmorrow> | (unsafePerformIO getLine) ? |
| 17:11:35 | <roconnor> | BONUS: I'm not sure that the Haskell 98 report says that about hGetContents. Checking now. |
| 17:11:41 | <lilac> | mmorrow: no, no unsafe* used. |
| 17:11:55 | <mux> | actually, there is a new page for the vim scripts there: http://projects.haskell.org/haskellmode-vim/ |
| 17:11:58 | <lilac> | mmorrow: just forkIO, hGetContents, hPutStr, hClose and createPipe |
| 17:12:00 | <mmorrow> | lilac: what are you using |
| 17:12:12 | <mmorrow> | oh, hGetContents |
| 17:12:15 | <lilac> | yeah :) |
| 17:12:22 | <roconnor> | BONUS: I ususally think of hGetContents as part of concurrent programming. |
| 17:12:59 | <mmorrow> | lilac: err, i still don't see how you're doing it |
| 17:13:00 | <BONUS> | i dont have anything against it, as long as it's used wisely |
| 17:13:03 | <roconnor> | and that hGetContents is allowed to read the file whenever it feels like. |
| 17:13:08 | <lilac> | mmorrow: did you see my hpaste? |
| 17:13:12 | <mmorrow> | lilac: oh, no |
| 17:13:43 | <BONUS> | if you have a good understanding of how your IO works, you can maintin purity throughout most of your program |
| 17:13:53 | <mmorrow> | lilac: oh, well you still are in IO |
| 17:14:10 | <lilac> | http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5078#a5079 |
| 17:14:16 | <lilac> | ^^ someOperation is /not/ still in IO |
| 17:14:23 | <lilac> | and yet it performs IO. |
| 17:14:28 | <roconnor> | ``Computation hGetContents hdl returns the list of characters corresponding to the unread portion of the channel or file managed by hdl, which is made semi-closed. |
| 17:14:44 | <roconnor> | I see nothing about when this reading is done. |
| 17:14:52 | <mmorrow> | i thought you mean you had a function (keybd :: String) that read from the keybd without unsafePerformIO |
| 17:14:57 | <mmorrow> | *meant |
| 17:15:05 | <lilac> | mmorrow: not a function. it's a one-hit thing, sadly |
| 17:15:10 | <lilac> | mmorrow: but i have a plan... |
| 17:15:15 | <mmorrow> | lilac: just have it take a () |
| 17:15:23 | <mmorrow> | :: () -> String |
| 17:16:11 | <lilac> | mmorrow: how would i implement that? |
| 17:16:17 | <mmorrow> | and `seq` or direct cps can sequence what's forced |
| 17:16:34 | <ski> | (mmorrow : why would that work, barring `unsafePerformIO' ?) |
| 17:16:48 | <mmorrow> | ski: because you use unsafePerformIO of course |
| 17:16:51 | <mmorrow> | :) |
| 17:17:29 | <lilac> | mmorrow: i can only perform IO once for each time 'interleaveIO' is called |
| 17:17:41 | <lilac> | mmorrow: however, it can call itself, so perhaps... |
| 17:17:59 | <mmorrow> | oh, i was talking about if you were to just use unsafePerformIO |
| 17:18:08 | <ski> | maybe one could do something with an oracle tree .. |
| 17:18:14 | <mmorrow> | withLine k = let !x = unsafePerformIO getLine in k x |
| 17:18:48 | <mmorrow> | IO doesn't have to be a monad.. |
| 17:19:01 | <ski> | ? |
| 17:19:32 | <mmorrow> | ski: e.g. you can use cps |
| 17:19:55 | <lilac> | mmorrow: but the point was to prove that lazy IO violates referential transparency, and not just to the extent of deferring file reads |
| 17:20:07 | <lilac> | mmorrow: that is, it allows you to defer /all/ IO operations |
| 17:20:15 | <lilac> | i think that's kinda scary |
| 17:20:41 | <gio123> | hi |
| 17:20:46 | <mmorrow> | withIO io k = let !x = unsafePerformIO io in k x |
| 17:21:17 | <mmorrow> | withIO getLine $ \line -> withIO (putStrLn line) $ \() -> 42 |
| 17:21:50 | <ski> | (mmorrow : oh, you meant "I/O" as opposed to `IO') |
| 17:21:59 | <mmorrow> | ski: ah, heh, yes |
| 17:22:18 | <kau> | hello! |
| 17:22:30 | <roconnor> | lazy IO doesn't violate referential transparency. I thought we settled that. |
| 17:22:51 | <mmorrow> | roconnor: what's the definition of lazy IO ? |
| 17:23:03 | <mmorrow> | (not a rhetorical question) |
| 17:23:05 | <roconnor> | hGetContents |
| 17:23:10 | <mmorrow> | ah |
| 17:23:16 | <BONUS> | i'd say any IO action that uses unsafeInterleavedIO |
| 17:23:41 | <BONUS> | it is my understanding that it doesn't violate referential transparency, but it does violate purity in the sense that it matters when an expression is evaluated |
| 17:24:15 | <ski> | only if we expect to be able to easily keep track / reason about, when effects in `IO' happens |
| 17:24:28 | <ski> | (that's not a small "only", granted) |
| 17:25:23 | <mmorrow> | withIO getLine $ \line -> withIO (putStrLn line) $ \() -> 42 |
| 17:25:24 | <mmorrow> | getLine >>= \line -> putStrLn line >>= \() -> return 42 |
| 17:25:39 | <roconnor> | IMHO, unsafeInterleavedIO should be thought of concurrent programming and treated as such. ie, your code shouldn't depend on when terms are evaluated. and should work if hGetContents is strict or anywhere in between. |
| 17:25:40 | <mmorrow> | (just thought that was worth explicitly pointing out) |
| 17:25:43 | <roconnor> | but that is just me. |
| 17:25:45 | <roconnor> | :) |
| 17:26:33 | <Saizan> | that's not quite accurate either |
| 17:27:04 | <kau> | I've came across something in the libraries documentation: about ArrowChoice, it says "This class underlies the if and case constructs in arrow notation." How does this come from?? |
| 17:27:24 | <copumpkin> | kau: have you played with arrow notation? |
| 17:27:29 | <kau> | no |
| 17:27:31 | <mmorrow> | kau: the compiler explicitly mapping that syntax to that class |
| 17:27:33 | <Saizan> | it doesn't ever perform the effects on its own if you don't force the result, that's a very peculiar scheduler :) |
| 17:27:33 | <ski> | kau : the arrow notation is desugared into operations from the various basic arrow classes |
| 17:27:40 | <kau> | OK |
| 17:27:41 | <mmorrow> | kau: just like "do" notation to monads |
| 17:27:56 | <kau> | i wonder how to make an "if" in pointless notation |
| 17:28:01 | <ski> | Saizan : true |
| 17:28:28 | <kau> | like this: f a = if a then XXX else YYY but without the "a" |
| 17:28:33 | <mmorrow> | if' a b c = if a b c |
| 17:28:34 | <ski> | @let if_ f t b = if b then t else f |
| 17:28:35 | <lambdabot> | Defined. |
| 17:28:40 | <gio123> | does somebody use beamer latex? |
| 17:29:11 | <magical_pony> | ya |
| 17:29:15 | <kau> | i thought ArrowChoice could help me |
| 17:29:24 | <ski> | kau : for arrow notation you have to start with `proc <pat> -> <cmd>' iirc |
| 17:29:33 | <copumpkin> | kau: without the a? |
| 17:29:46 | <copumpkin> | kau: you mean you want a function that behaves like the if expression? |
| 17:29:58 | <ski> | kau : maybe you want (angelic ?) nondeterminism ? |
| 17:30:28 | <kau> | let me find back my exemple |
| 17:31:40 | <kau> | here it is. I'm still working on the "cosmicomics" trick |
| 17:32:04 | <kau> | i found that one-liner: uncurry (==) $ sort *** sort $ splitAt =<< (`div` 2) . length $ "cosmiccomics" |
| 17:32:17 | <copumpkin> | lol |
| 17:32:25 | <copumpkin> | that's pretty golfed |
| 17:32:36 | <kau> | :) |
| 17:32:46 | <copumpkin> | so want to check for the language ww? :P |
| 17:33:05 | <kau> | just to get me use to the arrow etc... |
| 17:33:36 | <copumpkin> | well, I mean, you want to check that the passed in is two identical strings placed adjacent to one another? |
| 17:33:53 | <copumpkin> | I don't think ArrowChoice will help you there |
| 17:34:36 | <kau> | yes, the goal is to find auto-anagrams, the rigth part is an anagram of the left part |
| 17:34:37 | <copumpkin> | if you want to golf it more though, you can do join (***) sort, even though that's longer |
| 17:34:48 | <copumpkin> | oh, I see |
| 17:35:38 | <kau> | how would you write it? |
| 17:35:42 | <conal> | sclv: i just replied to your comment: http://conal.net/blog/posts/the-c-language-is-purely-functional/#comment-21113 |
| 17:35:54 | <copumpkin> | something like that :) |
| 17:36:22 | <copumpkin> | bbl :) |
| 17:36:25 | <kau> | OK, but it doesn't work for string with odd lentgh |
| 17:38:28 | <kau> | that's why i wanted an "if" pointfree |
| 17:39:12 | <mux> | :wq |
| 17:39:16 | <mux> | wwops, sorry |
| 17:40:08 | <persica> | Heh, I type ":w" all the time in random windows. |
| 17:40:54 | <vininim> | I keep trying to move the cursos in irssi with C-f and C-b. |
| 17:41:00 | <vininim> | *cursor |
| 17:41:19 | <msch> | hi, can someone elighten me what "Occurs check: cannot construct the infinite type" is all about? (http://hpaste.org/fastcgi/hpaste.fcgi/view?id=5080#a5080) |
| 17:42:11 | <ski> | (msch : just guessing, you're confusing a list with a list element .. maybe by using `(:)' in place of `(++)' or vice versa) |
| 17:42:17 | <ski> | ACTION looks at paste |
| 17:42:58 | <ski> | msch : it might help if you provide the errant code in question too .. e.g. annotate that paste with it |
| 17:43:48 | <msch> | ski: I just did. Thanks for your help :) The code is based on chapter 17 of Haskell: The craft of functional programming |
| 17:45:18 | <ski> | ACTION remembers reading that chapter for the first time :) |
| 17:46:06 | <kau> | where can i find infos about the if desugarisation?? |
| 17:46:14 | <msch> | it doesn't seem that hard at first, but then I got that error and I've been stuck with it since Tuesday |
| 17:46:39 | <lilac> | > (\s->any(==sort s).map(sort.join (++))$tails s) "cosmiccomics" |
| 17:46:41 | <lambdabot> | True |
| 17:46:43 | <msch> | http://www.complang.tuwien.ac.at/knoop/lehre/ss2009/ffp185210/ffp_lu06_090507.pdf That's the assignment. But please don't complete it for me, just help me solve my occurs check problem |
| 17:46:43 | <ski> | msch : i think i see the problem |
| 17:46:44 | <lilac> | kau ^^ that's how i'd do it |
| 17:47:00 | <msch> | ski: neither do i :) But did you run the code? |
| 17:47:11 | <Twey> | ACTION protests for significant whitespace around operators |
| 17:47:19 | <ski> | msch : i said i think i *do* see the problem :) |
| 17:47:26 | <kau> | lilac: can't understand anything ^^ |
| 17:47:26 | <mux> | ACTION seconds Twey |
| 17:47:29 | <msch> | ski: oh... sorry.... |
| 17:47:39 | <ski> | (and no, i'm just type-checking the code in my head) |
| 17:47:46 | <ski> | msch : generally, in such cases, it helps to put type signatures on the definitions |
| 17:47:49 | <ski> | anyway |
| 17:47:52 | <lilac> | kau: it's an auto-anagram if any suffix, when doubled, is an anagram of the original |
| 17:47:59 | <ski> | c_aexpr = c_term `alt` (c_aexpr >*> c_aop >*> c_term) |
| 17:47:59 | <mmorrow> | if TH is on, you need a space after '$' |
| 17:47:59 | <lilac> | kau: so i test for that |
| 17:48:01 | <ski> | c_term = c_factor `alt` (c_term >*> c_mop >*> c_factor) |
| 17:48:15 | <ski> | msch : you need to use `build' on the left argument to `alt' there |
| 17:48:57 | <msch> | ski: that's it? could you maybe explain why? |
| 17:49:13 | <TomMD> | I need a simple XML library with which to generate KML files - any suggestions? |
| 17:49:14 | <Fred320> | @src foldr |
| 17:49:14 | <lambdabot> | foldr f z [] = z |
| 17:49:15 | <lambdabot> | foldr f z (x:xs) = f x (foldr f z xs) |
| 17:49:21 | <TomMD> | No, foldr won't help me. |
| 17:49:23 | <TomMD> | ;-) |
| 17:49:29 | <Fred320> | lol |
| 17:49:29 | <ski> | msch : assume that `c_aexpr >*> c_aop >*> c_term' will parse values of form `(expression,(operator,term))' |
| 17:49:43 | <kau> | lilac: "join" and "any" are strangers for me |
| 17:49:53 | <ski> | msch : then the left argument to `alt', i.e. `c_term' will parse expressions of form `term' |
| 17:50:08 | <ski> | msch : those two kinds of values are not compatible/mixable |
| 17:50:11 | <lilac> | > (\s->any(on(==)sort$s).map(join(++))$tails s) "cosmiccomics" |
| 17:50:13 | <lambdabot> | True |
| 17:50:18 | <lilac> | yay, shorter |
| 17:50:32 | <ski> | msch : `alt' takes to parsers that returnes parsed values *of*the*same*type* |
| 17:50:44 | <Cale> | kau: any is a handy function. any p xs checks if any element of xs is able to make the condition p true |
| 17:50:52 | <Cale> | > any even [1,3,5,9] |
| 17:50:53 | <lambdabot> | False |
| 17:50:56 | <Cale> | > any even [1,3,5,8,9] |
| 17:50:58 | <lambdabot> | True |
| 17:51:00 | <ski> | msch : what you need to do is probably to build a proper Algebraic Data Type for C Expressions |
| 17:51:06 | <lilac> | kau: join f = (\x -> f x x) |
| 17:51:13 | <Fred320> | @pf 1 |
| 17:51:14 | <lambdabot> | Maybe you meant: bf pl |
| 17:51:15 | <lilac> | kau: it's more general than that, but that's what i'm using |
| 17:51:17 | <MyCatVerbs> | ski: don't we already have one in Language.C? |
| 17:51:18 | <Fred320> | @pl 1 |
| 17:51:19 | <lambdabot> | 1 |
| 17:51:37 | <msch> | ski: Yeah, now when I look at alt's signature it's obvious :) Thank you very much! |
| 17:51:37 | <Fred320> | @pl \x rest = map (x:) rest ++ rest |
| 17:51:37 | <lilac> | kau: so join (++) = \xs -> xs ++ xs |
| 17:51:38 | <lambdabot> | (line 1, column 9): |
| 17:51:38 | <lambdabot> | unexpected "=" |
| 17:51:38 | <lambdabot> | expecting pattern or "->" |
| 17:51:42 | <Cale> | 1 has no lambdas in it, so @pl is unlikely to do anything with it ;) |
| 17:51:53 | <lilac> | @unpl 1 |
| 17:51:53 | <lambdabot> | 1 |
| 17:51:55 | <lilac> | :( |
| 17:52:00 | <Cale> | @pl x rest -> map (x:) rest ++ rest |
| 17:52:00 | <lambdabot> | (line 1, column 8): |
| 17:52:01 | <lambdabot> | unexpected ">" or "-" |
| 17:52:01 | <lambdabot> | expecting variable, "(", operator or end of input |
| 17:52:02 | <Cale> | @pl \x rest -> map (x:) rest ++ rest |
| 17:52:03 | <lambdabot> | join . ((++) .) . map . (:) |
| 17:52:06 | <Fred320> | @pl \x rest -> map (x:) rest ++ rest |
| 17:52:06 | <lambdabot> | join . ((++) .) . map . (:) |
| 17:52:07 | <ski> | MyCatVerbs : msch is doing this as excercise with parsing monads (i presume) |
| 17:52:09 | <Fred320> | ah |
| 17:52:09 | <monadic_kid> | does it conform to C99? |
| 17:52:15 | <lilac> | @pl (\s->any(on(==)sort$s).map(join(++))$tails s) |
| 17:52:15 | <lambdabot> | ap ((. map (join (++))) . any . on (==) sort) tails |
| 17:52:16 | <TomMD> | @pl map (\x -> x / 2) |
| 17:52:17 | <lambdabot> | map (/ 2) |
| 17:52:21 | <monadic_kid> | Langauge.C i mean |
| 17:52:28 | <ski> | msch : btw, you use your `Token' type in an odd way |
| 17:52:41 | <Fred320> | that pl term is completely unreadable :) |
| 17:52:54 | <lilac> | wow, @pl made it shorter! |
| 17:52:58 | <TomMD> | It is called pointless for a reason. |
| 17:53:02 | <Fred320> | LOL |
| 17:53:06 | <lilac> | > ap((.map(join(++))).any.on(==)sort)tails "cosmiccomics" |
| 17:53:07 | <lambdabot> | True |
| 17:53:18 | <ski> | msch : usually one have parsers output some kind of Abstract Syntax Tree (represented as a Haskell Algebraic Data Type, here) |
| 17:53:23 | <msch> | ski: what exactly do you mean? Token is provided by the lecturer so I'm not free to change it anyways. |
| 17:53:35 | <kau> | lilac: and what is "on"? |
| 17:53:41 | <ski> | msch : these parsers then either consume some kind of characters .. or they *consume* tokens |
| 17:54:03 | <ski> | msch : your parsers that (attempt to) *produce* tokens when parsing |
| 17:54:08 | <lilac> | kau: "on (==) sort" would usually be written as "(==) `on` sort" |
| 17:54:23 | <ski> | msch : i suspect your lecturer meant you to *consume* tokens when parsing |
| 17:54:26 | <lilac> | kau: (*) `on` f = \x y -> f x * f y |
| 17:54:48 | <monadic_kid> | You know what would be cool is if we could start with referentially transparent subset of C, then add in a simple dependant type system with linear types, support for multi-stagging then you can replace all the stupidness of C++ |
| 17:54:50 | <ski> | (msch : and maybe have a preliminary lexing stage that translates a string to a list of tokens, to then be fed to the parsing proper) |
| 17:55:01 | <ski> | s/that/there/ |
| 17:55:26 | <Fred320> | @src join |
| 17:55:27 | <lambdabot> | join x = x >>= id |
| 17:55:32 | <lilac> | > (.map(join(++))).any.on(==)sort`ap`tails "moresomorose" |
| 17:55:33 | <lambdabot> | precedence parsing error |
| 17:55:33 | <lambdabot> | cannot mix `(.)' [infixr 9] and `ap' ... |
| 17:56:26 | <ski> | msch : anyway, the key to solve the particular problem you're having is, i think, to first define an AST ADT, and then to use `build' on the parsers passed to `alt', to make sure the types match |
| 17:56:41 | <Cale> | That expression has been overgolfed I think. |
| 17:57:00 | <monadic_kid> | In the SAC programming language, the SAC team did a good job defining a grammar which represnets a referentially transparent subset of C. That might be a good place to start |
| 17:57:22 | <inimino> | lilac: why are you using tails instead of cutting it in half first? |
| 17:57:34 | <kau> | lilac: yes why?? |
| 17:58:37 | <kau> | inimino: how would you cut it in half? |
| 17:59:05 | <Cale> | monadic_kid: It seems like an okay idea except that... wouldn't the result be a completely different programming language? It seems a bit funny to start with C at all. |
| 17:59:08 | <lilac> | inimino: because it's shorter that way :) |
| 17:59:14 | <pejo> | monadic_kid, are you using "simple dependent types" in the meaning that there are few typing rules for the language? |
| 17:59:36 | <lilac> | inimino, kau: we were golfing, right? |
| 17:59:46 | <ski> | msch : anyway, good luck (i'm off) |
| 17:59:54 | <msch> | ski: well i was thinking i could follow you till that last message :) As far as I understand it this parser throws away the actual information (which Numeral, Identifier) and only outputs a list of Tokens. So I was thinking it'd be easy to just `build` the tokens "inline" and later pattern-match the resulting tupel to get a list. Are you telling me I should use build only after I have parsed the whole input? |
| 18:00:08 | <monadic_kid> | Cale: I'm talking abut in the context of C++ replacement |
| 18:00:08 | <msch> | ski: ok, thank you for your help! Have a nice remaining day! |
| 18:00:09 | <kau> | lilac: what does golfing means (sorry i'm french) |
| 18:00:47 | <inimino> | lilac: I guess I missed the beginning of that ;-) |
| 18:01:04 | <lilac> | kau: implementing something in a minimal number of (key)strokes |
| 18:01:12 | <kau> | OK |
| 18:01:24 | <inimino> | kau: like the game of golf, the goal is to get the lowest score |
| 18:01:52 | <mux> | kau: you should come in #haskell.fr - it's dramatically empty :-) |
| 18:02:36 | <Tristan1> | Hello everyone |
| 18:02:52 | <kau> | inimino: OK! |
| 18:03:15 | <Tristan1> | I'd like to know if there is any implementation for Hidden Markov Models in Haskell ? |
| 18:03:30 | <kau> | mux: yes this is sad haskell doesn't enthusiast french people |
| 18:03:40 | <mux> | Tristan1: yes, I've seen a hmm module on hackage |
| 18:03:47 | <mux> | kau: *nods* |
| 18:04:04 | <kau> | i feel alone too! |
| 18:04:04 | <Tristan1> | especially: is there allready a framework for human movement recognition ? |
| 18:04:07 | <monadic_kid> | pejo: simple in the sense of to not the extent of something like Epigram and simple in the sense of syntatically. |
| 18:04:23 | <mux> | Tristan1: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hmm |
| 18:04:54 | <mux> | Tristan1: I have no idea what it's worth though, I hardly know what an HMM is |
| 18:05:00 | <kau> | mux: to change that, i'm into tutorials translations ;) |
| 18:05:16 | <mux> | kau: cool, good luck with that! |
| 18:11:23 | <kau> | is (->) an operator? ghci bugs me on :t (->) |
| 18:11:56 | <monochrom> | It is not an operator. |
| 18:12:11 | <kau> | what is it? |
| 18:12:16 | <mux> | it would be a type operator |
| 18:12:20 | <mux> | but it's necessarily builtin |
| 18:12:32 | <monochrom> | It is used in types but not values. |
| 18:12:40 | <kau> | mux: thats what i wanted to hear ;) |
| 18:13:10 | <mux> | monochrom: because it's builtin and we have other syntactic forms (hopefully!) to introduce function values |
| 18:13:33 | <monochrom> | > let 1->2 = 3 in 1->2 |
| 18:13:34 | <lambdabot> | <no location info>: parse error on input `->' |
| 18:13:41 | <monochrom> | Amazing. |
| 18:14:33 | <monochrom> | I see, -> is a reserved word. |
| 18:14:35 | <mux> | (->) is usually considered a type operator when defining calculus, and GHC also allows to use it as such in class instances |
| 18:14:49 | <kau> | but (->) is an instance of Arrow (->)! |
| 18:14:55 | <mux> | ACTION nods |
| 18:15:15 | <kau> | arent class instances tyoes? ;) |
| 18:15:17 | <MyCatVerbs> | You can't ask :t (->) because (->) isn't a funciton. |
| 18:15:20 | <MyCatVerbs> | *function, gah. |
| 18:15:20 | <mux> | an arrow is the generalisation of the idea of a type that goes from some type to another |
| 18:15:42 | <MyCatVerbs> | You can ask :k (->), because (->) is a type constructor. |
| 18:15:42 | <mux> | kau: not necessarily, class instances can have higher kinds |
| 18:15:46 | <MyCatVerbs> | @kind (->) |
| 18:15:47 | <lambdabot> | ?? -> ? -> * |
| 18:15:54 | <mux> | like * -> * which makes them not types but type operators |
| 18:16:05 | <kau> | yeah, can't understand this. |
| 18:16:23 | <mux> | this is very easy, kinds are like the types of types |
| 18:16:24 | <monochrom> | Monad is an example. You say "Monad Maybe" not "Monad (Maybe a)". |
| 18:16:31 | <kau> | OK |
| 18:16:47 | <mux> | and monotype (ie Int, Char, [Bool]) has kind * |
| 18:16:52 | <mux> | s/and/any/ |
| 18:17:01 | <mux> | Maybe has kind * -> * |
| 18:17:12 | <mux> | because it's as if it takes another type as a parameter to produce a type |
| 18:17:18 | <mux> | Maybe Int has kind * |
| 18:17:26 | <mux> | Arrow has kind * -> * -> *, etc |
| 18:17:26 | <kau> | the language of kinds is a real language (ie i can code with it)? or only documentary? |
| 18:17:29 | <gio123> | http://pastebin.com/d4434692a |
| 18:18:45 | <mux> | kau: it all boils down to what you call "code", but no you cannot write algorithms with it |
| 18:19:23 | <kau> | mux: what the use of kinds |
| 18:19:24 | <kau> | ? |
| 18:19:41 | <mux> | kau: they are only useful to detect malformed type expressions |
| 18:19:46 | <mux> | such as Int Int |
| 18:20:13 | <kau> | so it's a language for compilers? |
| 18:20:18 | <mux> | GHC has extended kinds too, (with ? characters), but I have no idea what they are used for |
| 18:21:14 | <mux> | kau: it's a type system for type expressions, and thus permits to statically check type expressions |
| 18:21:30 | <mux> | just as the type system permits to check expressions statically |
| 18:21:38 | <monochrom> | Three cases: unboxed type, boxed type, don't-care |
| 18:22:23 | <monochrom> | The kind of -> probably illustrates all three cases. |
| 18:22:29 | <kau> | so there are types of types, are there types of types of types? lol |
| 18:22:37 | <mux> | no :) |
| 18:22:43 | <monadic_kid> | checkout the kernal grammar (firgure 1), it's a functional subset of C and it's quite small :) http://www.sac-home.org/publications/sac-overview-jfp-03.pdf |
| 18:23:36 | <mux> | kau: types for types become useful when your types get more expressive, if I'm not mistaken System F has kinds |
| 18:23:58 | <mux> | it's packaged with parametric polymorphism :-P |
| 18:24:02 | <kau> | F#? |
| 18:24:13 | <mux> | System F is the second order lambda calculus |
| 18:24:33 | <monadic_kid> | lol |
| 18:24:48 | <monochrom> | Coq supports countably many levels of "type of types". |
| 18:24:54 | <mux> | heh |
| 18:25:14 | <mux> | the whole Set Set1 thing? |
| 18:25:34 | <mux> | ACTION needs to improve his dependent typing skills |
| 18:26:01 | <kau> | monochrom: what the use of these levels? i have to settle and thing about that... |
| 18:27:52 | <mathijs_> | anyone tried to get hs-plugins installed recently? |
| 18:28:11 | <mathijs_> | hackage says it won't build on ghc8.10 |
| 18:30:14 | <TomMD> | @hackage hs-plugins |
| 18:30:15 | <lambdabot> | http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hs-plugins |
| 18:31:20 | <mathijs_> | try without the hs- TomMD |
| 18:31:30 | <mathijs_> | http://hackage.haskell.org/cgi-bin/hackage-scripts/package/plugins |
| 18:31:32 | <TomMD> | mathijs: I can install it, but is there a simple test I can run? |
| 18:31:42 | <monochrom> | The "set of all sets" paradox can be resolved in three ways. First is ignore it. Second is disallow it. Third is stratification, i.e., countably many levels, so "the set of all level-0 sets" is a level-1 set, in general "the set of all level-n set" is a level-(n+1) set. |
| 18:31:44 | <TomMD> | GHC 6.10.3 btw. |
| 18:32:12 | <mathijs_> | I'm not even thinking about running it |
| 18:32:14 | <mathijs_> | yet |
| 18:32:16 | <mathijs_> | tbh |
| 18:32:35 | <c_wraith> | monochrom: which of those categories does constructionism fit into? |
| 18:32:42 | <mathijs_> | It seems to depend on cabal 1.4.0 |
| 18:32:50 | <mathijs_> | erm 1.4.* |
| 18:32:59 | <monochrom> | I think it depends on whose constructionism. |
| 18:33:08 | <mathijs_> | ?? |
| 18:33:22 | <monochrom> | Coq is one constructionism. It uses stratification. |
| 18:33:52 | <monochrom> | s/whose/who's/ |
| 18:34:14 | <mathijs_> | while ghc doesn't want cabal 1.4 |
| 18:34:35 | <c_wraith> | Hmm.. What's the one I was looking into? Perceptualism, maybe? |
| 18:34:57 | <c_wraith> | No, that's not the name of it. |
| 18:35:04 | <c_wraith> | And I don't seem to have the paper anymore. grr. |
| 18:36:35 | <mathijs_> | hmm i can actually get the old cabal version that seems to work |
| 18:39:38 | <bos31337> | i like it when people report easy-to-fix bugs. |
| 18:40:03 | <Cale> | The disallowing and stratification approaches are actually quite closely related. Ignoring the problem is a strange approach, since being able to construct a contradiction is usually troublesome. (Though in Haskell, for instance, we're more concerned with which proofs are available for a type, and not whether a proof exists or not.) |
| 18:41:07 | <Cale> | The sense in which disallowing a set of all sets is related to the stratification approach is that it's exactly what you get when you take the fragment of the stratified set theory which only discusses level 0 sets. |
| 18:41:42 | <roconnor> | there are two types of stratification. You allow subtyping or not allow subtyping in universes. |
| 18:42:03 | <kau> | monochrom: the "set of all sets" paradox is from a famous mathematician, isn't it? I can't remember who? |
| 18:42:14 | <monochrom> | Russell. |
| 18:42:15 | <Cale> | Russell |
| 18:42:16 | <roconnor> | AFAIK Agda has no subtyping, while Coq des. |
| 18:42:19 | <kau> | yeah! |
| 18:42:28 | <roconnor> | me! |
| 18:42:35 | <Cale> | It's actually what you get when you allow a set of all sets, together with comprehension. |
| 18:42:37 | <monochrom> | But he has so many paradoxes that "Russell Paradox" is ambiguous. Only second to Zeno. |
| 18:43:16 | <Cale> | If you throw away comprehension, you could also avoid the problem, but that tends to completely destroy the sense that you have a set theory at all. |
| 18:43:21 | <roconnor> | however type in type isn't really the same as set in set because there is no comprehension axiom. |
| 18:43:28 | <roconnor> | It is more like Girard's paradox |
| 18:43:39 | <roconnor> | or rather is Girard's paradox |
| 18:44:20 | <kau> | what is Zeno? |
| 18:44:56 | <kau> | ha, Zénon d'Élée? |
| 18:44:58 | <roconnor> | And Girard's paradox is really the Burali-Forti paradox, as I understand it. |
| 18:45:12 | <monochrom> | My Paradox. |
| 18:46:02 | <Cale> | The set of all ordinal numbers one? |
| 18:46:28 | <roconnor> | the ordinal of all ordinals, ya. |
| 18:46:37 | <monochrom> | My Paradox: Is math contrived or inflicted? |
| 18:47:06 | <Cale> | contrived ;) |
| 18:48:23 | <monochrom> | The paradox is that most students find it both. Someone contrived math so as to inflict it on students. "Why can't I just have sin(x+y)=sin(x)+sin(y)? It's artificially made hard." |
| 18:48:27 | <roconnor> | Russell's paradox was not the first paradox in naive set theory. But, for some reason, it was the most damning. |
| 18:48:42 | <Cale> | monochrom: hehehe |
| 18:49:17 | <Cale> | roconnor: Hmm... what came before it historically? |
| 18:49:29 | <Cale> | It was something found in Frege's system, yeah? |
| 18:50:43 | <roconnor> | Cale: I understand that the problems of the largest ordinal and largest cardinal predate Russell's paradox |
| 18:50:46 | <roconnor> | but I'm not sure. |
| 18:51:00 | <kau> | can i have something like hoogle in ghci? |
| 18:51:01 | <Cale> | Frege's system is the first attempt at actually formalising set theory that I know of, and Russell was the one who pointed out the problem with unrestricted set comprehension in it. |
| 18:51:56 | <Cale> | kau: not really, though there's :browse |
| 18:52:38 | <kau> | Cale: i have no internet at work but i would like to install something like hoogle... |
| 18:52:42 | <rfmge> | kau: yup, there's a command line version of hoogle, in my .ghci file i have ':def hoogle \x -> return $ ":!hoogle --info --color " ++ x' |
| 18:52:42 | <roconnor> | I feel that the paradox of largest ordinal and Russell's paradox are quite different, even if set theory solve the both problems in one fell swoop. |
| 18:52:52 | <Cale> | rfmge: Oh, that's interesting :) |
| 18:53:22 | <byorgey> | rfmge: neat =) |
| 18:54:14 | <Cale> | roconnor: Yes, the way in which the contradiction arrives is quite different. |
| 18:55:14 | <copumpki> | thoughtpolice: around? |
| 18:56:57 | <rfmge> | kau: i also have the same thing but for 'pointfree', to mangle all my code into an unreadable mess |
| 18:57:19 | <Cale> | hehe |
| 18:58:46 | <wy> | hello |
| 18:59:13 | <mux> | wow, parsec 3 has ParsecT and can handle strict & lazy bytestrings! |
| 18:59:18 | <EvilTerran> | wy hello there :) |
| 18:59:19 | <mux> | why did noone tell me? ;-) |
| 18:59:22 | <monochrom> | ACTION rewrites The Lord of The Rings. The evil Sauron invented (not discovered!) the Ring of All Rings but he sucked at logic. So did pretty much everyone else, that's why he was unchallenged for a long time. After 1000 pages of wars and hobbit adventures, Frodo arrived at Mount Doom and asked an innocent but logical question. Then all evilness disappeared in a puff of logic. |
| 18:59:27 | <wy> | Hi EvilTerran |
| 18:59:39 | <wy> | I finally got to return to haskell :) |
| 19:00:01 | <wy> | after a year's "torture" by scheme .. hehe |
| 19:00:34 | <wy> | It's great that the knowledge is coming back very quickly. |
| 19:00:47 | <Fred320> | foldr (\x rest -> map (x:) rest ++ rest) [[]] "ABCDE" |
| 19:00:52 | <wy> | Just have one question by now. Is newtype definition still useful? |
| 19:00:54 | <Fred320> | > foldr (\x rest -> map (x:) rest ++ rest) [[]] "ABCDE" |
| 19:00:55 | <lambdabot> | ["ABCDE","ABCD","ABCE","ABC","ABDE","ABD","ABE","AB","ACDE","ACD","ACE","AC... |
| 19:01:02 | <Fred320> | > foldr (\x rest -> map (x:) rest ++ rest) [[]] "ABCD" |
| 19:01:03 | <lambdabot> | ["ABCD","ABC","ABD","AB","ACD","AC","AD","A","BCD","BC","BD","B","CD","C","... |
| 19:01:07 | <Fred320> | > foldr (\x rest -> map (x:) rest ++ rest) [[]] "ABC" |
| 19:01:08 | <lambdabot> | ["ABC","AB","AC","A","BC","B","C",""] |
| 19:01:11 | <tetha> | monochrom: just make sure those 1000 pages are like 900 pages of walking around, 90 pages of preparing for battle, 9 pages of walking into the battle and a page of battle. |
| 19:01:15 | <monadic_kid> | wy; of-course, why would that change? |
| 19:01:16 | <monochrom> | mux: Parsec 3 was announced in the mailing lists a hundred years ago. |
| 19:01:28 | <copumpki> | many moons ago |
| 19:01:31 | <wy> | I just though we may not still need it? |
| 19:01:48 | <wy> | The manual says that the only purpose of newtype is to reduce the overhead |
| 19:02:23 | <monochrom> | newtype is still useful. It still reduces overhead. |
| 19:02:36 | <wy> | So I think why don't we just translate every "data T1 = T1 T2" into "newtype T1 = T1 T2" ? |
| 19:02:56 | <roconnor> | data is more lazy than newtype |
| 19:02:57 | <wjt> | as with many things in Haskell, the answer is "bottoms". |
| 19:03:06 | <Fred320> | @src reverse |
| 19:03:07 | <lambdabot> | reverse = foldl (flip (:)) [] |
| 19:03:08 | <Berengal> | There's subtle semantic differences between data and newtype |
| 19:03:11 | <monochrom> | I sometimes enjoy the extra bottom. I mean T1 _|_ |
| 19:03:28 | <wy> | monochrom: really? |
| 19:03:33 | <roconnor> | but it is certainly true that 95% of the type that data could be newtype, it should be newtype. |
| 19:03:40 | <monochrom> | Perhaps I am perverse. |
| 19:03:46 | <roconnor> | s/type/time/ |
| 19:03:49 | <wy> | lol |
| 19:04:00 | <wy> | I understand now. Thanks |
| 19:04:01 | <Fred320> | @hoogle [t] -> [[t]] |
| 19:04:02 | <lambdabot> | Data.List inits :: [a] -> [[a]] |
| 19:04:02 | <lambdabot> | Data.List tails :: [a] -> [[a]] |
| 19:04:02 | <lambdabot> | Data.List groupBy :: (a -> a -> Bool) -> [a] -> [[a]] |
| 19:04:25 | <roconnor> | ACTION kinda wishes that newtype would give us unlifted tuples. |
| 19:04:31 | <wy> | monochrom: maybe it will be instructive if you give an example |
| 19:04:57 | <wy> | roconnor: Can't that be done with strictness analysis? |
| 19:05:01 | <Berengal> | roconnor: As in, only one constructor but several fields? |
| 19:05:10 | <roconnor> | Berengal: ya |
| 19:05:18 | <Berengal> | Yeah, I could see how that'd be useful |
| 19:05:25 | <monochrom> | I don't know how to give an example of why I enjoy something. |
| 19:05:50 | <roconnor> | wy: It's true that strict fields in data types comes pretty close to what I want. |
| 19:05:54 | <wy> | monochrom: You could try. I'm a weird person too ;) |
| 19:07:04 | <thoughtpolice> | copumpki: yo |
| 19:07:16 | <copumpki> | thoughtpolice: Igloo is racing us to the gold! |
| 19:07:19 | <copumpki> | ;) |
| 19:08:22 | <Berengal> | @type f x = f x |
| 19:08:24 | <lambdabot> | parse error on input `=' |
| 19:08:31 | <Berengal> | @type let f x = f x in f |
| 19:08:33 | <lambdabot> | forall t t1. t -> t1 |
| 19:08:58 | <copumpki> | that's a pretty exciting function |
| 19:09:04 | <monochrom> | OK, here is an example. When I see T1 _|_, I feel peace and comfort. |
| 19:09:16 | <Berengal> | copumpki: yeah, safe cast ;) |
| 19:09:19 | <copumpki> | lol |
| 19:09:31 | <copumpki> | as safe as the fix id "cast" |
| 19:10:40 | <monochrom> | @type fix id |
| 19:10:42 | <lambdabot> | forall a. a |
| 19:10:49 | <copumpki> | :( |
| 19:11:30 | <monochrom> | @type let x=x in x {- same thing -} |
| 19:11:33 | <lambdabot> | forall t. t |
| 19:11:36 | <copumpki> | yup |
| 19:11:38 | <Berengal> | @type let f x = f x in fix f |
| 19:11:40 | <lambdabot> | forall a. a |
| 19:12:10 | <copumpki> | :t let f x = (fix id) x |
| 19:12:12 | <lambdabot> | <no location info>: not an expression: `let f x = (fix id) x' |
| 19:12:16 | <copumpki> | :t let f x = (fix id) x in f |
| 19:12:18 | <lambdabot> | forall t t1. t -> t1 |
| 19:13:11 | <Berengal> | @type forever |
| 19:13:13 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => m a -> m () |
| 19:13:25 | <Berengal> | I thought forever was m a -> m b ... |
| 19:13:42 | <EvilTerran> | ?hoogle exitWith |
| 19:13:42 | <lambdabot> | System.Exit exitWith :: ExitCode -> IO a |
| 19:13:49 | <wy> | monochrom: I have some problem making an example about the extra indirection |
| 19:14:00 | <EvilTerran> | Berengal, ^ that might've been the non-returning monadic function you were thinking of |
| 19:14:05 | <roconnor> | ah, the eternal, "what is the type of forever" question. |
| 19:14:06 | <wy> | my code looks like newtype Natural = Natural Integer |
| 19:14:17 | <wy> | kk1 (Natural x) = 1 |
| 19:14:38 | <wy> | kk1 bot succeed with 1 instead of diverge |
| 19:14:39 | <Berengal> | EvilTerran: No, I'm pretty sure it was forever. exitWith might be non-returning, but it's halting |
| 19:15:01 | <Berengal> | EvilTerran: Besides, exitWith is in IO |
| 19:15:13 | <wy> | gosh ... I see the problem... |
| 19:15:26 | <Berengal> | ghci says: forever :: (Monad m) => m a -> m b |
| 19:15:28 | <roconnor> | > forever (Left "done") |
| 19:15:29 | <lambdabot> | Left "done" |
| 19:15:41 | <monochrom> | data Int = I# Int# is not supposed to be optimized further. Then again that's just useful for compiler writers. |
| 19:15:43 | <EvilTerran> | Berengal, true; i just figured they both produce monadic actions that don't have a result value |
| 19:15:54 | <roconnor> | I think the type of forever may have changed at some point in time. |
| 19:16:11 | <EvilTerran> | ...that's vaguely ironic |
| 19:16:11 | <Berengal> | roconnor: Yeah, I think it was m () in 6.8 or something |
| 19:16:26 | <roconnor> | > forever [] |
| 19:16:28 | <lambdabot> | [] |
| 19:16:33 | <roconnor> | > forever Nothing |
| 19:16:34 | <lambdabot> | Nothing |
| 19:16:47 | <Fred320> | @hoogle [t] -> [(t, t)] |
| 19:16:47 | <lambdabot> | Test.QuickCheck two :: Monad m => m a -> m (a, a) |
| 19:16:48 | <lambdabot> | Prelude zip :: [a] -> [b] -> [(a, b)] |
| 19:16:48 | <lambdabot> | Data.List zip :: [a] -> [b] -> [(a, b)] |
| 19:17:03 | <vininim> | > forever error "error" |
| 19:17:18 | <lambdabot> | thread killed |
| 19:17:31 | <vininim> | k |
| 19:17:42 | <roconnor> | > forever (error "error") |
| 19:17:43 | <lambdabot> | No instance for (Show (m ())) |
| 19:17:43 | <lambdabot> | arising from a use of `show' at <i... |
| 19:18:04 | <roconnor> | @type (forever error) |
| 19:18:05 | <lambdabot> | [Char] -> () |
| 19:18:19 | <roconnor> | reader monad? |
| 19:18:24 | <dmwit> | yes |
| 19:18:45 | <roconnor> | this is the problem with too many instances. type errors stop occuring. :) |
| 19:19:06 | <dmwit> | Just wait until you take out the occurs check. ;-) |
| 19:19:06 | <Berengal> | roconnor: Nah, it's always reader when you're confused |
| 19:19:11 | <roconnor> | > foever (error "error") :: Identity () |
| 19:19:13 | <leimy> | :t forever |
| 19:19:13 | <lambdabot> | Not in scope: `foever' |
| 19:19:14 | <lambdabot> | forall (m :: * -> *) a. (Monad m) => m a -> m () |
| 19:19:19 | <roconnor> | > forever (error "error") :: Identity () |
| 19:19:21 | <lambdabot> | No instance for (Show (Identity ())) |
| 19:19:21 | <lambdabot> | arising from a use of `show... |
| 19:19:28 | <roconnor> | oh really? |
| 19:19:32 | <wy> | lunch time. see you guys |
| 19:19:35 | <roconnor> | > forever (error "error") :: Maybe () |
| 19:19:36 | <lambdabot> | * Exception: error |
| 19:19:52 | <roconnor> | > runIdentity $ forever (error "error") |
| 19:19:53 | <vininim> | strange |
| 19:20:08 | <lambdabot> | thread killed |
| 19:20:20 | <roconnor> | hmm |
| 19:20:25 | <roconnor> | I guess Identity is too lazy |
| 19:20:27 | <EvilTerran> | > flip runState (10,[]) $ runErrorT $ forever (do (x,xs) <- get; if x > 0 then put (x-1,x:xs) else mzero) :: (Either String (), (Int,[Int])) |
| 19:20:29 | <lambdabot> | (Left "",(0,[1,2,3,4,5,6,7,8,9,10])) |
| 19:20:52 | <dmwit> | ?src Identity |
| 19:20:53 | <lambdabot> | newtype Identity a = Identity { runIdentity :: a } |
| 19:21:09 | <roconnor> | ?src Identity (>>) |
| 19:21:10 | <lambdabot> | Source not found. I can't hear you -- I'm using the scrambler. |
| 19:21:15 | <EvilTerran> | > fix Identity |
| 19:21:16 | <roconnor> | ?src (>>) Identity |
| 19:21:16 | <lambdabot> | Source not found. Listen, broccoli brains, I don't have time to listen to this trash. |
| 19:21:17 | <lambdabot> | Occurs check: cannot construct the infinite type: a = Identity a |
| 19:21:17 | <lambdabot> | ... |
| 19:21:58 | <dmwit> | (>>) = flip const |
| 19:22:10 | <dmwit> | So, yeah, too lazy. |
| 19:22:49 | <dmwit> | > foldl1' (flip const) (repeat (error "error")) |
| 19:22:51 | <lambdabot> | * Exception: error |
| 19:23:00 | <EvilTerran> | i guess the problem is that the pattern (Identity x) will always match successfully |
| 19:23:03 | <dmwit> | > foldl1 (flip const) (repeat (error "error")) |
| 19:23:16 | <dmwit> | EvilTerran: Yep, that's a newtype for you. |
| 19:23:22 | <roconnor> | the problem is that flip const is lazy in it's first argument |
| 19:23:26 | <roconnor> | really really lazy |
| 19:23:41 | <EvilTerran> | > case undefined of Identity _ -> "sooo laaazzzyyy..." |
| 19:24:04 | <dmwit> | ?botsnack? |
| 19:24:16 | <roconnor> | , let (Identity _) = undefined in "sooo laaazzzyyy..." |
| 19:24:16 | <ray> | :) |
| 19:24:16 | <EvilTerran> | dmwit, dammit, you broke the bot |
| 19:24:17 | <lunabot> | luna: Not in scope: data constructor `Identity' |
| 19:24:32 | <EvilTerran> | roconnor, let bindings are non-strict anyway |
| 19:24:35 | <roconnor> | :) |
| 19:24:48 | <EvilTerran> | , let Just x = undefined in () |
| 19:24:49 | <lunabot> | () |
| 19:24:56 | <roconnor> | yep |
| 19:25:14 | <roconnor> | >, case undefined of _ -> "sooo laaazzzyyy..." |
| 19:25:18 | <roconnor> | oops |
| 19:25:21 | <roconnor> | , case undefined of _ -> "sooo laaazzzyyy..." |
| 19:25:22 | <lunabot> | "sooo laaazzzyyy..." |
| 19:25:52 | <jonafan> | i like haskell |
| 19:25:54 | <ray> | is !_ possible? |
| 19:26:21 | <ziman> | > case 3 of !_ -> "foo" |
| 19:26:39 | <ziman> | , case 3 of !_ -> "foo" |
| 19:26:40 | <lunabot> | "foo" |
| 19:26:52 | <ray> | i guess there's no reason for it not to be, but it looks so ugly |
| 19:27:51 | <copumpki> | thoughtpolice: what if Igloo beats us???? |
| 19:29:17 | <Fred320> | @hoogle [t] -> [t] |
| 19:29:27 | <copumpki> | tail? |
| 19:29:32 | <vininim> | id |
| 19:29:35 | <copumpki> | lol |
| 19:29:46 | <roconnor> | ACTION wants gold too |
| 19:29:48 | <copumpki> | init |
| 19:29:59 | <ski> | (roconnor : `Identity' is strict .. as EvilTerran's example demonstrates) |
| 19:30:06 | <copumpki> | ACTION shows roconnor the bottom of the rainbow |
| 19:30:10 | <monochrom> | evil Identity |
| 19:30:12 | <roconnor> | ski: I mean (>>) is lazy |
| 19:30:13 | <ray> | id is the only one that works on [] |
| 19:30:16 | <ray> | so id wins |
| 19:30:22 | <mauke> | drop 1 |
| 19:30:35 | <copumpki> | that's not a named function, sry |
| 19:30:36 | <roconnor> | const [] |
| 19:30:37 | <ski> | aye |
| 19:30:44 | <vininim> | @bot |
| 19:30:44 | <lunabot> | :) |
| 19:30:45 | <monochrom> | The bottom of the rainbow is an infinite loop. |
| 19:30:51 | <ray> | const [] is a -> [t] |
| 19:30:53 | <copumpki> | roconnor: that's [t] -> [t1] |
| 19:30:59 | <copumpki> | ah, yeah |
| 19:31:03 | <roconnor> | hoggle will find it |
| 19:31:06 | <roconnor> | hoogle |
| 19:31:10 | <vininim> | lambda bot was dos'ed by Identity? omg |
| 19:31:12 | <copumpki> | ACTION hoggles |
| 19:31:12 | <ray> | hoggle |
| 19:31:31 | <hoggle> | it's like a cute little pig |
| 19:31:31 | <roconnor> | @slap hoggle |
| 19:31:37 | <lambdabot> | ACTION slaps hoggle |
| 19:31:47 | <hoggle> | @hoggle a -> b |
| 19:31:53 | <lambdabot> | Unsafe.Coerce unsafeCoerce :: a -> b |
| 19:31:59 | <hoggle> | yay levenshtein |
| 19:31:59 | <lambdabot> | Prelude ($) :: (a -> b) -> a -> b |
| 19:32:03 | <roconnor> | undefined |
| 19:32:09 | <lambdabot> | Plugin `hoogle' failed with: thread killed |
| 19:32:21 | <hoggle> | wow, lambdabot is being slow |
| 19:32:33 | <vininim> | someone is fiddling with it |
| 19:32:33 | <Cale> | It looks like it just reconnected |
| 19:32:38 | <ski> | presumably it is still joining a lot of channels |
| 19:32:40 | <Cale> | So it's joining channels |
| 19:32:42 | <ray> | thread killed |
| 19:32:48 | <Cale> | I wonder why it reconnected |
| 19:32:59 | <ray> | someone was strict with it |
| 19:33:02 | <vininim> | Cale: Identity killed it |
| 19:33:11 | <vininim> | egodeath or something |
| 19:33:26 | <Cale> | what? |
| 19:33:37 | <ray> | very hofstadter |
| 19:33:41 | <monochrom> | haha |
| 19:34:29 | <hoggle> | I ddin't know erlang was made in factories |
| 19:37:36 | <gwern> | hoggle: well, java is. why not erlang? |
| 19:37:54 | <hoggle> | erlang-factory.com! |
| 19:38:26 | <gwern> | but it goes to show that erlang is more primitive than java. when was the last time you saw a factory factory in erlang, eh? |
| 19:38:37 | <hoggle> | true, erlang fails :( |
| 19:38:41 | <monochrom> | You can make babies in factories too. |
| 19:38:42 | <hoggle> | metafactory factory |
| 19:39:32 | <Berengal> | Is a factory factory factory something like fmap fmap fmap? |
| 19:39:41 | <ray> | vaguely |
| 19:39:52 | <skorpan> | what's the relation? |
| 19:39:56 | <tetha> | anything with more than 2 factories in it is something horrible |
| 19:39:59 | <tetha> | imho |
| 19:40:03 | <ray> | factories are probably a functor |
| 19:40:12 | <pumpkin_> | anything with more than 0 factories is an abomination, imnsho |
| 19:40:13 | <lambdabot> | pumpkin_: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 19:40:16 | <ray> | so you can fmap fmap fmap into your factory factory factory |
| 19:40:23 | <inimino> | it's more object-orientationy |
| 19:40:24 | <Berengal> | tetha: I would've left out "more than 2" |
| 19:40:32 | <conal> | inimino: :) |
| 19:40:34 | <lambdabot> | conal: You have 1 new message. '/msg lambdabot @messages' to read it. |
| 19:41:12 | <Berengal> | Well, a factory factory factory is like three layers of factories, but fmap fmap fmap is only two layers... |
| 19:41:32 | <inimino> | see, factories save typing |
| 19:41:44 | <Berengal> | There's also fmap . fmap |
| 19:42:00 | <roconnor> | Berengal: you mean fmap fmap fmap |
| 19:42:08 | <ray> | fmap `fmap` fmap |
| 19:42:18 | <roconnor> | oops |
| 19:42:19 | <Berengal> | roconnor: Those are the same, are they not? |
| 19:42:21 | <roconnor> | I'm slow |
| 19:43:13 | <conal> | i like the visual distinction of "fmap . fmap", because it emphasizes the generality of the fmap's |
| 19:43:25 | <conal> | and that first, second, etc can be substituted. |
| 19:43:33 | <conal> | semantic editor combinators in general. |
| 19:43:45 | <byorgey> | conal: I think people only like "fmap fmap fmap" for its mind-bendingness =) |
| 19:43:52 | <byorgey> | I hope no one would ever use it in real code... |
| 19:44:11 | <tetha> | heh, so I guess the n-fmap-haskell programmer is like the n-star-c-programmer :) |
| 19:44:27 | <byorgey> | conal: I like that about "fmap . fmap" too, though |
| 19:44:29 | <monochrom> | I used 3 stars in C. |
| 19:44:42 | <conal> | byorgey: :) |
| 19:45:10 | <ray> | kleene stars |
| 19:45:59 | <mkaemmer> | monochrom: you should use an infinite number of stars by expanding *p to *&*&*&*&*...p |
| 19:46:01 | <byorgey> | @remember conal The C ADT is implemented simply as String (or char *, for you type theorists, using a notation from Kleene) |
| 19:46:01 | <lambdabot> | I will never forget. |
| 19:46:28 | <byorgey> | conal: hehe, that blog post was hilarious =) |
| 19:46:38 | <ray> | i nearly choked to death laughing |
| 19:46:40 | <skorpan`> | if i have [x, y, z] and w and i want (x + (y + (z * w))), how would i do that? |
| 19:46:46 | <monochrom> | Haha conal |
| 19:47:02 | <conal> | byorgey: thanks! that post pretty much leapt out of me. |
| 19:47:04 | <ray> | and i don't even read haskell blogs, i just happened to go to planet.haskell at random |
| 19:47:29 | <conal> | i hadn't noticed the C/Kleene thing until a moment before I typed it. |
| 19:48:08 | <byorgey> | I wonder if Kleene's notation inspired C syntax? sounds far-fetched but... ? |
| 19:49:00 | <Botje> | skorpan`: sum (init l ++ w * last l) |
| 19:49:05 | <byorgey> | skorpan`: it's ALMOST a fold, but not quite... |
| 19:49:10 | <skorpan`> | byorgey: exactly |
| 19:49:21 | <wy> | I didn't know that Kleene invented another star :) |
| 19:49:26 | <skorpan`> | Botje: but imagine that it's not really + and *, but completely different binary functions |
| 19:49:28 | <conal> | byorgey: sounds far-fetched to me too, but then who knows. |
| 19:49:29 | <Botje> | foldr (+) (w * last l) (init l) |
| 19:49:35 | <Botje> | better? |
| 19:49:42 | <skorpan`> | Botje: possibly, i can't test it atm |
| 19:50:03 | <conal> | as my dad would say "all the stories i make up are true" |
| 19:50:03 | <Botje> | > let l = [x,y,z] in foldr (+) (w * last l) (init l) |
| 19:50:07 | <lambdabot> | x + (y + w * z) |
| 19:50:19 | <byorgey> | conal: hehe =) |
| 19:50:20 | <Botje> | looks like it's what you want :) |
| 19:50:25 | <skorpan`> | > let l = [a,b,c,d] in foldr (+) (w * last l) (init l) |
| 19:50:27 | <lambdabot> | a + (b + (c + w * d)) |
| 19:50:31 | <skorpan`> | yep, looks right |
| 19:50:37 | <pumpkin_> | that isn't very purty though! |
| 19:51:03 | <byorgey> | > foldr (\e -> ((e+) .)) (*w) [x,y,z] |
| 19:51:05 | <lambdabot> | Overlapping instances for Show (Expr -> Expr) |
| 19:51:05 | <lambdabot> | arising from a use... |
| 19:51:08 | <Botje> | that it isn't :) |
| 19:51:20 | <byorgey> | > foldr (\e -> ((e+) .)) (*w) [x,y,z] [x,y,z] |
| 19:51:22 | <lambdabot> | Couldn't match expected type `[Expr]' against inferred type `Expr' |
| 19:51:25 | <pumpkin_> | that's nicer :) |
| 19:51:27 | <pumpkin_> | when it works |
| 19:51:40 | <byorgey> | @type foldr (\e -> ((e+) .)) (*w) [x,y,z] |
| 19:51:41 | <lambdabot> | Expr -> Expr |
| 19:51:47 | <byorgey> | @type foldr (\e -> ((e+) .)) (*w) [1,2,3] |
| 19:51:48 | <lambdabot> | Expr -> Expr |
| 19:51:54 | <byorgey> | argh |
| 19:51:56 | <skorpan`> | is it really nicer? to me it just seems less understandable |
| 19:51:59 | <byorgey> | @type foldr (\e -> ((e+) .)) (*10) [1,2,3] |
| 19:52:01 | <lambdabot> | forall a. (Num a) => a -> a |
| 19:52:13 | <pumpkin_> | hmm, you need a final 0? |
| 19:52:16 | <byorgey> | @type foldr (\e -> ((e+) .)) (*10) [1,2,3] $ 1 |
| 19:52:18 | <lambdabot> | forall a. (Num a) => a |
| 19:52:30 | <wy> | monochrom: I still haven't found the key to show the difference between newtype and data |
| 19:52:30 | <pumpkin_> | it's a 0 isn't it? |
| 19:52:32 | <pumpkin_> | > foldr (\e -> ((e+) .)) (*10) [1,2,3] $ 1 |
| 19:52:34 | <lambdabot> | 16 |
| 19:53:09 | <byorgey> | hmm, well, I think we could make this work in theory, but I have just aptly demoonstrated how confusing it is =) |
| 19:53:33 | <mkaemmer> | > foldl (\e -> ((e+) .)) (*10) [1,2,3] $ 0 |
| 19:53:34 | <lambdabot> | Occurs check: cannot construct the infinite type: a = a1 -> a |
| 19:53:34 | <lambdabot> | Prob... |
| 19:55:20 | <riddochc> | Got a question on laziness and data structures. The RWH book says that the 'lines' function returns a list of strings, one per line. Suppose I'm computing a mean of a list of numbers in a file, one per line, and I'm folding over the output of lines. Is Haskell going to build a big list of the lines before processing any of them, or is it going to read the next line just before it'll get used? |
| 19:55:37 | <Botje> | the second |
| 19:55:51 | <Botje> | laziness means the compiler can interleave computations for you |
| 19:56:14 | <byorgey> | riddochc: it depends how you implement the averaging operation. |
| 19:56:14 | <mauke> | riddochc: depends on how you read the lines |
| 19:56:40 | <byorgey> | riddochc: if the averaging operation needs two passes over the list, one for the sum, and one for the length, then it will have to keep the entire list around in memory. |
| 19:56:42 | <Fred320> | @pl concat . map |
| 19:56:42 | <lambdabot> | join . map |
| 19:57:07 | <Botje> | ... shit |
| 19:57:12 | <byorgey> | but if you keep a running sum and count as you do one pass over the list, and compute the average from that at the end, then laziness should kick in and the whole thing will take constant memory. |
| 19:57:16 | <Botje> | i'm utterly baffles as to how i'm supposed to write a conclusion |
| 19:57:25 | <riddochc> | byorgey: right, I'm assuming a running sum. |
| 19:58:33 | <qaz> | > let decent_avg_function xs = foldl ((summa, len) next -> (summa+next,len+1)) (0,0) xs in decent_avg_function [1,2,3] |
| 19:58:34 | <lambdabot> | <no location info>: parse error on input `->' |
| 19:58:42 | <qaz> | > let decent_avg_function xs = foldl ((summa, len) next -> (summa+next,len+1)) (0,0) xs in decent_avg_function [1,2,3] |
| 19:58:43 | <lambdabot> | <no location info>: parse error on input `->' |
| 19:58:47 | <byorgey> | riddochc: the main point is, this has nothing to do with 'lines' --- lines is perfectly lazy, so if you write a nice consumer for the list that lines produces, things will work fine. |
| 19:59:23 | <riddochc> | So, is all I/O then delayed until its ready to be processed? I'm coming from languages like, for example, ruby, where IO.readlines is different from IO.each_line - the first reads *all* lines, the second reads one line at a time and yields it to a block. |
| 19:59:25 | <byorgey> | so the short answer to your question is "the second, but be careful how you average" =) |
| 19:59:41 | <qaz> | > let decent_avg_function xs = foldl ((summa, len) next -> (summa+next,len+1)) (0,0) xs in decent_avg_function [1,2,3] |
| 19:59:42 | <lambdabot> | <no location info>: parse error on input `->' |
| 20:00:05 | <skorpan`> | > let decent_avg_function xs = foldl (\(summa, len) next -> (summa+next,len+1)) (0,0) xs in decent_avg_function [1,2,3] |
| 20:00:05 | <byorgey> | riddochc: there are a few I/O operations, such as getContents and readFile, which operate lazily. Not all I/O is. |
| 20:00:06 | <lambdabot> | (6,3) |
| 20:00:11 | <byorgey> | riddochc: they're kind of magical though. |
| 20:00:31 | <riddochc> | Wow. A bot that runs arbitrary code. That seems... unwise. ;) |
| 20:00:36 | <Berengal> | There's also unsafeInterleaveIO, which is the nub of the magic |
| 20:00:43 | <qaz> | > let decent_avg_function xs = let (a,b) = foldl (\(summa, len) next -> (summa+next,len+1)) (0,0) xs in a / b in decent_avg_function [1,2,3] |
| 20:00:44 | <lambdabot> | 2.0 |
| 20:00:52 | <byorgey> | riddochc: it doesn't run IO operations. |
| 20:00:57 | <Berengal> | > print "hello" |
| 20:00:59 | <byorgey> | and is otherwise rather tightly bolted down. =) |
| 20:00:59 | <lambdabot> | <IO ()> |
| 20:01:03 | <wy> | Any good examples to show the difference between newtype and data types? |
| 20:01:20 | <Berengal> | wy: Appart from the restrictions on newtype? |
| 20:01:57 | <wy> | Berengal: What do you mean by restrictions? |
| 20:02:02 | <byorgey> | wy: the biggest difference---that there is no runtime overhead for newtypes---is hard to see directly with an example |
| 20:02:03 | <wy> | I see... |
| 20:02:04 | <wy> | yes |
| 20:02:23 | <mauke> | newtype R = R R |
| 20:02:25 | <Berengal> | wy: Well, newtypes can only have one constructor and one field |
| 20:02:28 | <mauke> | how many values in this type? |
| 20:02:51 | <pumpkin_> | two! |
| 20:02:58 | <Berengal> | two? |
| 20:02:59 | <byorgey> | one! |
| 20:03:00 | <mauke> | which ones? |
| 20:03:10 | <Berengal> | I'd say bottom is the only one... fix R |
| 20:03:18 | <pumpkin_> | undefined and fix R |
| 20:03:19 | <hatds> | is that even legal? o.o |
| 20:03:32 | <riddochc> | Hmm. I may be getting way ahead of myself here, but how does lazy I/O interact with things like network sockets or pipes, where the amount of data that can be worked on at any given point can change? |
| 20:03:38 | <Berengal> | pumpkin_: By that logic R (fix R) is a third value |
| 20:03:38 | <byorgey> | pumpkin_: fix R *is* undefined |
| 20:03:40 | <wy> | mauke: That's a weird example |
| 20:03:47 | <Zao> | riddochc: Blocking? |
| 20:03:52 | <mauke> | wy: it's condensed |
| 20:03:59 | <pumpkin_> | can't you distinguish between fix R and undefined? |
| 20:04:06 | <mauke> | pumpkin_: try it! |
| 20:04:24 | <pumpkin_> | ACTION tries it! |
| 20:04:28 | <wy> | mauke: strange... |
| 20:04:35 | <byorgey> | pumpkin_: this is the point: newtypes are unlifted, i.e. there's no tag stored at runtime |
| 20:04:39 | <pumpkin_> | oh |
| 20:04:43 | <pumpkin_> | ok :) |
| 20:04:44 | <wy> | data R = R R is not valid but newtype R = R R is ... |
| 20:04:45 | <pumpkin_> | ACTION doesn't try it |
| 20:04:57 | <mauke> | wy: both are valid |
| 20:05:14 | <wy> | oh my fault... |
| 20:05:17 | <byorgey> | data R = R R is quite valid, and has omega many values |
| 20:05:26 | <hatds> | pretty useless datatype though, since you can't build any values without a party crasher like undefined or error --right? |
| 20:05:35 | <riddochc> | Where would I find out which I/O functions work lazily and which don't? |
| 20:05:39 | <Berengal> | Hehe, show (fix R) and show (undefined :: R) both result in the same infinite string |
| 20:05:46 | <byorgey> | hatds: you can build r = R r ! |
| 20:05:53 | <byorgey> | no undefined or error there |
| 20:05:57 | <mauke> | it's a type with no real values, similar to 'data X' (no constructors) |
| 20:05:58 | <hatds> | ok |
| 20:06:05 | <mauke> | except the 'data X' stuff is not H98 |
| 20:06:38 | <pumpkin_> | that's cool |
| 20:06:41 | <byorgey> | hatds: wait, it depends which version of R you were talking about |
| 20:06:41 | <pumpkin_> | undefined :: R |
| 20:06:50 | <wy> | mauke: has newtype R = R R only one value? |
| 20:06:54 | <mauke> | wy: yes |
| 20:07:01 | <pumpkin_> | even undefined is that value! |
| 20:07:03 | <pumpkin_> | ACTION is impressed |
| 20:07:11 | <hatds> | byorgey: what other R? |
| 20:07:17 | <mauke> | the 'data' version shall be called data S = S S |
| 20:07:19 | <byorgey> | hatds: newtype R = R R, or data R = R R ? |
| 20:07:23 | <byorgey> | ok =) |
| 20:07:33 | <Berengal> | With newtype R = R R deriving Show, I can't tell the difference between fix R and undefined, but with data R = R R I can... |
| 20:07:51 | <byorgey> | hatds: R is useless. with S, you can do what I said: make s = S s, which doesn't use undefined or error. |
| 20:08:24 | <wy> | I still want an example to show an observable difference |
| 20:08:45 | <Berengal> | wy: Try what I just did |
| 20:08:48 | <hatds> | we've gone a bit on a tangent for this poor guy :) |
| 20:09:11 | <mauke> | wy: R undefined `seq` () |
| 20:09:16 | <Berengal> | newtype R = R R, data S = S S, both deriving show. Now try show (undefined :: R) and show (undefined :: S) |
| 20:09:18 | <hatds> | normally, a data constructor represents another layer of indirection. Newtype constructors remove that |
| 20:09:57 | <monochrom> | His question is why not always optimize "data D = C X" to newtype. |
| 20:10:23 | <mauke> | because that changes the semantics |
| 20:10:27 | <mauke> | so it's not an optimization |
| 20:10:37 | <Vulpyne> | At my work, I frequently run into a situation where I want to pull large text files into Map. I usually have a problem with running out of memory and/or stack space, so I'm doing something horribly wrong. Here is an example: http://www.hpaste.org/fastcgi/hpaste.fcgi/view?id=5084 |
| 20:11:09 | <Vulpyne> | Anyone have an idea of what I can change? I've tried strict and lazy bytestrings, and I'm using foldl'. |
| 20:12:10 | <wy> | @src seq |
| 20:12:10 | <lambdabot> | Source not found. And you call yourself a Rocket Scientist! |
| 20:13:10 | <Fred320> | @pl \x y -> x ++ e:y |
| 20:13:10 | <lambdabot> | (. (e :)) . (++) |
| 20:13:45 | <wy> | Berengal: That's weird... |
| 20:14:10 | <Berengal> | wy: It's also why they're different |
| 20:14:47 | <Berengal> | wy: http://www.haskell.org/haskellwiki/Newtype |
| 20:15:28 | <jeff_s_> | I thought the following was a valid type declaration: "data Equation = [Math]". Did I do something wrong? |
| 20:15:37 | <mauke> | jeff_s_: missing constructor |
| 20:15:39 | <Berengal> | jeff_s_: You need a constructor |
| 20:15:40 | <jeff_s_> | "data Equation = Data.List Math" worked |
| 20:15:49 | <mauke> | that surprises me |
| 20:15:59 | <Berengal> | Wow, could that be legal? |
| 20:16:06 | <jeff_s_> | well, it parses anyway |
| 20:16:10 | <Vulpyne> | jeff_s_: You might mean: type Equation = [Math] ... That creates an alias not an actual type. |
| 20:16:18 | <Twey> | o.@ |
| 20:17:05 | <Berengal> | I can't get anything like Data.List to parse as a constructor |
| 20:17:11 | <hatds> | yea me neither |
| 20:17:21 | <jeff_s_> | oh I see what's going on better. Sorry, it's my old ML habits getting in the way. |
| 20:17:33 | <Fred320> | inits "ABC" |
| 20:17:35 | <Vulpyne> | Does anyone have any ideas regarding my question? |
| 20:17:36 | <Fred320> | > inits "ABC" |
| 20:17:38 | <lambdabot> | ["","A","AB","ABC"] |
| 20:18:10 | <jeff_s_> | but ya "data Math = LP | RP | Plus | Sub | Mul | Div | Var Char |
| 20:18:10 | <jeff_s_> | data Equation = Data.List Math" parses, dunno if it should or not |
| 20:18:20 | <mauke> | doesn't parse for me |
| 20:18:25 | <mauke> | try.hs:5:16: Qualified name in binding position: Data.List |
| 20:18:34 | <jeff_s_> | dunno what to tell you :\\ |
| 20:19:01 | <Berengal> | Perhaps paste the whole code, in case there's something else interfering with the parsing? |
| 20:19:03 | <mauke> | you should tell me that you're using hugs |
| 20:19:11 | <jeff_s_> | ghc |
| 20:19:57 | <jeff_s_> | I pasted all the code. If I put "main = print "hi"" after it, it compiles |
| 20:20:07 | <jeff_s_> | er, sorry no, 1 sec |
| 20:20:11 | <Cale> | Vulpyne: hmm... just a random shot in the dark here: what happens if you replace M.insert with M.insertWith' const ? |
| 20:20:17 | <wy> | Berengal: Thanks very much. That's the example I wanted to make |
| 20:20:32 | <jeff_s_> | ok now I get a type error, but it parses |
| 20:20:42 | <mreh> | how does one import something from a module that has been imported into another module through the parent module? |
| 20:20:51 | <Cale> | Vulpyne: If that doesn't help, then I'll actually think about it more carefully :) |
| 20:21:02 | <wy> | It would take more thinking how these examples are related |
| 20:21:04 | <qaz> | > let flipWithMe f a b = flip $ flip f a b in flipWithMe (-) 10 20 |
| 20:21:04 | <Cale> | Vulpyne: Also, just to check, you are compiling with -O2 yeah? |
| 20:21:05 | <lambdabot> | Overlapping instances for Show (b -> a -> c) |
| 20:21:05 | <lambdabot> | arising from a use ... |
| 20:21:19 | <Vulpyne> | I wasn't, but I'll try that. |
| 20:21:22 | <byorgey> | mreh: you can only do so if the second module re-exports the thing from the parent module. |
| 20:21:23 | <qaz> | > let flipWithMe f a b = (flip . flip) f a b in flipWithMe (-) 10 20 |
| 20:21:24 | <lambdabot> | -10 |
| 20:21:35 | <mreh> | byorgey: thanks |
| 20:21:49 | <Vulpyne> | cale: Unfortunately, it doesn't seem to have made a difference. |
| 20:21:51 | <byorgey> | in which case you just import it as normal. |
| 20:21:57 | <conal> | Cale: thanks for the blog comment. i just responded: http://conal.net/blog/posts/the-c-language-is-purely-functional/#comment-21125 |
| 20:22:11 | <Cale> | conal: Okay :) |
| 20:22:26 | <Fred320> | behold my permutation function :) |
| 20:22:29 | <Fred320> | > foldr (\x rest -> concat $ map (\list -> zipWith (\a z -> a ++ x:z) (inits list) (tails list)) rest) [[]] "ABC" |
| 20:22:30 | <lambdabot> | ["ABC","BAC","BCA","ACB","CAB","CBA"] |
| 20:22:41 | <mauke> | needs more runStateT |
| 20:22:59 | <wy> | Berengal: So for the example on the wikipage, because (Foo1 _) will be used to structurally match undefined, it goes into infinite loop |
| 20:23:45 | <wy> | but (Foo3 _) is identical to _, so it is not looked at |
| 20:24:21 | <Berengal> | wy: No, (Foo1 _) looks for the constructor Foo1, which it can't find in 'undefined', so bottoms out |
| 20:24:36 | <Berengal> | Foo3 has no constructor, so basically that part is correct |
| 20:25:00 | <Vulpyne> | Somehow I feel like I've fixed this before, but I can't remember. I haven't done haskell programming in a while. |
| 20:25:08 | <mreh> | what's the most idiomatic way of updating a record? |
| 20:25:18 | <Berengal> | wy: data Foo1 = Foo1 Int can either be _|_, Foo1 _|_ or Foo1 Int, where _|_ is bottom |
| 20:25:24 | <Vulpyne> | rec { field = val } |
| 20:25:35 | <Berengal> | wy: newtype Foo3 = Foo3 Int can either be _|_ or Foo3 Int |
| 20:25:42 | <Vulpyne> | Doesn't update it though, returns a new one with the change. |
| 20:26:08 | <wy> | Berengal: Maybe I can just think of Foo3 as Int? |
| 20:26:12 | <mreh> | Vulpyne, of course |
| 20:26:14 | <mreh> | thanks |
| 20:26:31 | <EvilTerran> | ACTION wishes for a syntax something like "foo { field <- fn }" to desugar to "foo { field = fn (field foo) }" |
| 20:26:45 | <wy> | So there will be a tag in the object with Foo1? |
| 20:26:48 | <Berengal> | wy: Yeah, it's certainly correct, appart from the class instances and the fact that it's a completely new type... otherwise, it behaves exactly the same |
| 20:27:00 | <mreh> | EvilTerr |