Experimental IRC log haskell-2009-05-20

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