Created
April 12, 2013 22:39
-
-
Save anonymous/5375768 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
00:17:34 <retronym> trepidacious_: comonad/costate isn't really neccessary for lenses. try this presentation: http://www.youtube.com/watch?v=efv0SQNde5Q | |
00:18:03 ? nomadmonad and milessabin quit | |
00:18:07 <edwardk> hey that looks familiar | |
00:18:38 ? jesnor ([email protected]) quit: Ping timeout: 240 seconds | |
00:20:52 <gseitz> shouldn't costate just be an implementation detail | |
00:20:53 <gseitz> ? | |
00:21:04 ? pantsman and j0ran quit | |
00:21:24 <larsrh> edwardk: are you aware of an introductory paper about comonads? | |
00:21:43 <edwardk> not really. i gave a talk on them at the first boston haskell i should have some slides handy | |
00:21:46 ? vsayer ([email protected]) quit: Ping timeout: 244 seconds | |
00:21:59 <edwardk> http://comonad.com/haskell/Comonads_1.pdf | |
00:22:03 ? stephenjudkins ([email protected]) quit: Quit: stephenjudkins | |
00:22:07 <edwardk> it doesn't go very deep though | |
00:22:17 <larsrh> yeah, I already found that | |
00:22:24 <edwardk> just motivates the type signature and asks folks to provide derivations themselves for a couple of obvious ones | |
00:22:31 <mapreduce> This explains 'co' things in general but not particularly comonads: http://blog.sigfpe.com/2007/07/data-and-codata.html | |
00:22:48 <mapreduce> There appears to be a Comonad.Reader! | |
00:23:03 <edwardk> thats focused on the notion of codata, you can have a monad made out of a codata and a comonad made out of data | |
00:23:36 <edwardk> [] is a monad, even if its codata (can be infinitely large and lazy), (,)e is a comonad, even though its data | |
00:23:58 <edwardk> otoh, data Stream a = a :- Stream a is codata and a comonad | |
00:24:02 <edwardk> and Maybe is data and a monad | |
00:24:25 <edwardk> so all four parts of the square are inhabited ;) | |
00:24:40 <mapreduce> What's (,)e when it's at home? | |
00:25:17 ? hrehf ([email protected]) quit: Quit: bfg | |
00:25:20 <mapreduce> I should concentrate on edwardk talking on youtube instead of asking him questions here. :) | |
00:25:49 › j0ran ([email protected]) joined | |
00:25:54 <edwardk> at home? | |
00:26:08 <mapreduce> What's (,)e? | |
00:26:08 <edwardk> the edwardk on youtube has a pause button. me not so much ;) | |
00:26:15 <edwardk> lets translate it into scala | |
00:26:41 <mapreduce> "What's 'foo' when it's at home?" is a colloquialism. | |
00:27:03 ? j0ran ([email protected]) quit: Client Quit | |
00:27:20 <edwardk> case class Env[E,A](env: E, extract: A) { def extend[B](f: Env[E,A] => B) = Env(env, f(this)); def map[B](f: A => B) = Env(env,f(extract)) } | |
00:27:39 <edwardk> (,) e is partial application of the type (e,a) to just the first argument | |
00:27:45 <edwardk> you can't partially apply types in scala though | |
00:27:58 <mapreduce> ah, tuple.. | |
00:28:00 <edwardk> (e,a) = (,) e a | |
00:28:44 <edwardk> in scala you'd need to call it ({ type l[x] = (E,x) })#l | |
00:28:47 <mapreduce> You have to introduce an extra type to simulate partially applied types afaik. | |
00:28:51 <edwardk> yes | |
00:29:00 <edwardk> which is awesome for type inference =P | |
00:29:47 <edwardk> anyways there .extract takes an Env[E,A] => A and extend takes an Env[E,A] and a function from Env[E,A] => B an gives you an Env[E,B] | |
00:30:36 <edwardk> other comonad examples are things like the store comonad, which you can make lenses from, case class Store[S,A](f: S => A, s: S) { def extract = f(s); … } | |
New messages | |
00:31:13 <edwardk> and if you have a monoid handy you can make a comonad out of M => A | |
00:31:18 <edwardk> with a monoid on M | |
00:31:33 <larsrh> my memory betrayed me, I was thinking of http://www.cl.cam.ac.uk/~dao29/drafts/codo-notation-orchard12.pdf, but it's mainly about codo-notation | |
00:31:35 <trepidacious_> How do you get from wanting to know what a comonad is, to knowing enough that any of that makes sense? | |
00:31:37 <edwardk> i have a revision control monad/comonad that i've also been working on | |
00:32:13 › thereisnospoon ([email protected]) joined | |
00:32:17 <edwardk> you can make codo notation out of the existing monadic sugar, the types just turn out funny | |
00:32:18 <trepidacious_> It might just be me, but I can't understand any of this without some motivating examples | |
00:32:20 <edwardk> and its not very useful | |
00:32:35 <trepidacious_> but thanks everyone for the links, I'll have a look through :) | |
00:32:39 <edwardk> because all the structure in the comonad is going to be in the position you are pattern matching on, rather than in the right hand side where do sugar gives you space to put stuff | |
00:33:12 <edwardk> trepidacious_: monads are all about building stuff, if you think about it, a monad takes a structure, expands it, and then smashes the two layers flat, restoring some invariants. | |
00:33:13 <trepidacious_> and the explanation, it sounds great, I just understand so little to start with, I can't get anything further from any of the explanations | |
00:33:21 casualjim › casualjim_zzz | |
00:33:29 <edwardk> the list monad, takes a list, and for every element in the source list, applies a function getting new lists, and then flatMap smashes it all flat | |
00:33:29 <trepidacious_> trepidaciousOk I kind of get that | |
00:33:39 <edwardk> so you can only see a little piece when you are building a whole new thing | |
00:33:53 <trepidacious_> oops don't know why I'm talking to my own nick, sorry carry on :) | |
00:33:54 <multiHYP> is _ stolen from bash? | |
New messages | |
00:34:09 <edwardk> on the other hand a comonad is all about being able to SEE EVERYTHING, when you are making a new value to replace yourself in the next version of the structure. | |
00:34:10 <multiHYP> I'm going all wacko on yo a$$ | |
00:34:19 <edwardk> lets come up with a compelling example | |
00:34:23 <edwardk> say you have an array | |
00:34:32 <edwardk> lets try to make a comonad for image manipulation | |
00:35:05 <edwardk> case class Pointer[A](arr : Array[A], pos: Int) | |
00:35:14 <edwardk> where we have an array 'arr' of A's and a position in the array | |
00:35:18 <trepidacious_> Ah yeah I saw something like that in my wanderings | |
00:35:24 <multiHYP> seriously can someone help my conscious? | |
00:35:27 <edwardk> for now its just an Int, but if you want you can make it multidimensional, so you can have X and Y coordinates | |
00:35:36 <trepidacious_> much easier for me to understand in Scala than the Haskell I found it in earlier | |
00:35:40 <edwardk> multiHYP: lots of languages use _ for ignoring stuff in patterns | |
00:35:48 <mapreduce> Wow, scalaquery looks cool. | |
00:35:50 <multiHYP> please $_ | |
00:35:51 <mapreduce> def * = id ~ name ~ street ~ city ~ state ~ zip | |
00:36:12 <trepidacious_> So Pointer is to this comonad as Option is to the Option monad? | |
00:36:14 <edwardk> now, extract for this comonad just gets the element out of the current position. | |
00:36:16 <multiHYP> i have another monumental question in my pocket too :) | |
00:36:50 <multiHYP> is AnyValue of type AnyRef? | |
00:36:50 <edwardk> and extend is interesting. basically what you are going to do is take a function from Pointer[A] => B and use it and the Pointer[A] you have to start with to make a new Pointer[B] | |
00:37:15 • multiHYP goes into deep mode. | |
00:37:24 <trepidacious_> edwardk: Sorry one second before we go further | |
00:37:41 <jamil_1> edwardk: so extends is like bind | |
00:37:42 <edwardk> that is to say you have a function that expects to use an entire array of input values, and knowledge of the position it is replacing, and you want to apply that function to every position in the source array to make a new array of values | |
00:37:59 <edwardk> jamil_1: yes, except where bind can only see one tiny piece, extend can 'see' everything, but only builds one tiny piee | |
00:38:01 <edwardk> er piece | |
00:38:06 <trepidacious_> edwardk: IIRC, for a monad like List we "go" from A to List[A], or for option A to Option[A] | |
00:38:14 <edwardk> trepidacious_: yep | |
00:38:17 <trepidacious_> edwardk: What is the corresponding relationship for this Pointer thing? | |
00:38:17 casualjim_zzz › casualjim | |
00:38:27 <edwardk> here we go from extract :: Pointer[A] => A | |
00:38:39 <trepidacious_> So the important types are A and Pointer[A] ? | |
00:38:49 <edwardk> yeah | |
00:39:06 <edwardk> here we only have one constructor | |
00:39:11 ? bmahe (~bmahe@fsf/member/bmahe) quit: Quit: Leaving | |
00:39:30 <edwardk> Pointer is a special case of Store, which is built out of the same building blocks as State, just backwards | |
00:40:09 <trepidacious_> Store is the comonad of State then? The Lens paper calls it CoState? | |
00:40:18 <edwardk> we need two operations, def extract[A] : Pointer[A] => A and def extend[A,B](p: Pointer[A], f: Pointer[A] => B): Pointer[B] | |
00:40:30 <trepidacious_> ok | |
00:40:34 <edwardk> Store is the comonadic version of state, its built by taking the adjunction that gives rise to state and composing it in the opposite order | |
00:40:49 <edwardk> I _ really_ don't like the name CoState, because it isn't dual to state, its an adjunction composed differently | |
00:40:57 <larsrh> ! case class Pointer[A](arr : Array[A], pos: Int) | |
00:40:59 <multibot_> defined class Pointer | |
00:41:01 <edwardk> it gives no intuition and is an abuse of terminology | |
00:41:01 <trepidacious_> Take that, dibblego :) | |
00:41:20 <larsrh> ! def extract[A](ptr: Pointer[A]) = ptr.arr(ptr.pos) | |
00:41:21 <multibot_> extract: [A](ptr: Pointer[A])A | |
00:41:29 <edwardk> dibblego gets lots of lumps from me occasionally ;) | |
00:41:36 <trepidacious_> :) | |
00:41:48 <pmenon> is there a native scala lib that can convert maps to json strings ? | |
00:41:53 <edwardk> then extend is tricky, you need to loop over all positions and pass the function each position in turn, while using that to make the new array | |
00:41:55 <trepidacious_> ok extract makes sense, it is getting the "base" type A back from a Pointer[A]? | |
00:42:06 <edwardk> yep, it just extracts one value | |
00:42:34 <edwardk> you can make lots of comonadic 'actions' for Pointer, like one that rotates the current position one left, and then extracts the value | |
00:42:36 <mapreduce> szeiger: Is scalaquery based on lots of overloads of methods with varying tuple arities? | |
00:42:46 <mapreduce> szeiger: If so, did you try HList and hit a wall? | |
00:42:56 <edwardk> where you choose to either clamp or roll around to the other side when you go out of bounds | |
00:43:17 <trepidacious_> Extend sounds a little like map? | |
00:43:51 <larsrh> ! def extend[A, B](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.array.length map { i => f(Pointer(ptr.arr, i)) }, ptr.pos) | |
00:43:52 <multibot_> error: value array is not a member of Pointer[A] | |
00:43:53 <edwardk> so an action we can take in this comonad is to 'blur' it, for instance, we can have an action like def blur(p: Pointer[Double]): Double -- which takes the current position, asks for the values one position above, below, left or right of it, and averages them | |
00:43:53 <multibot_> def extend[A, B](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.array.length map { i => f(Pointer(ptr.arr, i)) }, ptr.pos) | |
00:43:54 <multibot_> ^ | |
00:43:59 <edwardk> trepidacious_: except it can see more | |
00:44:06 <edwardk> flatMap is also like map, except it can build more | |
00:44:14 <larsrh> ! def extend[A, B](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.arr.length map { i => f(Pointer(ptr.arr, i)) }, ptr.pos) | |
00:44:16 <multibot_> error: type mismatch; | |
00:44:17 <multibot_> found : scala.collection.immutable.IndexedSeq[B] | |
00:44:18 <multibot_> required: Array[B] | |
00:44:19 <multibot_> def extend[A, B](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.arr.length map { i => f(Pointer(ptr.arr, i)) }, ptr.pos) | |
00:44:20 <multibot_> ^ | |
00:44:25 ? MKamowski ([email protected]) quit: Ping timeout: 250 seconds | |
00:44:29 <edwardk> larsrh: yep | |
00:44:48 › Spion_ (~spion@unaffiliated/spion) joined | |
00:44:49 <edwardk> ! 0 until 10 | |
00:44:50 <multibot_> scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) | |
00:44:52 <larsrh> ! def extend[A, B : ClassManifest](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.arr.length.map(i => f(Pointer(ptr.arr, i))).toArray, ptr.pos) | |
00:44:54 <multibot_> error: Unable to unapply type `Int` into a type constructor of kind `M[_]` that is classified by the type class `scalaz.Functor` | |
00:44:56 <multibot_> 1) Check that the type class is defined by compiling `implicitly[scalaz.Functor[<type constructor>]]`. | |
00:44:57 <multibot_> 2) Review the implicits in object Unapply, which only cover common type 'shapes' | |
00:44:57 <multibot_> (implicit not found: scalaz.Unapply[scalaz.Functor, Int]) | |
00:44:59 <multibot_> def extend[A, B : ClassManifest](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer(0 until ptr.arr.length.map(i => f(Pointer(ptr.arr, i))).toArray, ptr.pos) | |
00:45:14 <edwardk> you are mapping the wrong thing, no? | |
00:45:21 <edwardk> you need parens around 0 until ptr.arr.length | |
00:45:26 <edwardk> unless i misparsed | |
00:45:29 <larsrh> yes | |
00:45:32 <trepidacious_> So blur is processing one element of the array, but using the context of the entire array, and that is the "type" of function that makes sense for a comonad? | |
00:45:39 <edwardk> yep | |
00:45:41 <larsrh> ! def extend[A, B : ClassManifest](ptr: Pointer[A], f: Pointer[A] => B): Pointer[B] = Pointer((0 until ptr.arr.length).map(i => f(Pointer(ptr.arr, i))).toArray, ptr.pos) | |
00:45:44 <multibot_> extend: [A, B](ptr: Pointer[A], f: Pointer[A] => B)(implicit evidence$1: ClassManifest[B])Pointer[B] | |
00:45:48 <trepidacious_> That makes a lot more sense | |
00:46:09 <edwardk> and then when you extend(blur) you'll get a function that takes an entire array with current position to a new array with current position where everything has been blurred | |
00:46:10 <larsrh> although it's not a real "extend" because we need the `ClassManifest` for array construction :) | |
00:46:15 <edwardk> notice the shape of the array did not and CANNOT change | |
New messages | |
00:46:18 <trepidacious_> was that last definition of extend from larsrh the right one? | |
New messages since you scrolled up | |
00:46:21 <edwardk> larsrh: yes | |
00:46:25 <larsrh> yay | |
00:46:37 <edwardk> you need to use something other than a scala array | |
00:46:45 <edwardk> just grab some crap out of the collections library ;) | |
00:46:57 <larsrh> IndexedSeq, perhaps | |
00:47:06 <edwardk> you can probably also do it by abusing the ClassManifest for AnyRef or somesuch | |
00:47:12 › plainflavored joined ? raichoo and nuttycom quit | |
00:47:28 <edwardk> trepidacious_: looks good to me | |
00:47:54 <trepidacious_> I need to take a log of this, and then try to write it up, would be very helpful | |
00:47:55 <edwardk> another example is that you can make a comonad for streams or non-empty lists in several ways, depending on whether or not you want causal or anticausal streams, etc. | |
00:48:09 <edwardk> another good one is that Promises or Futures can form a comonad in an imperative language | |
00:48:18 <trepidacious_> I'm having trouble keeping up in real-time, but it all makes a lot of sense I think ;) | |
00:48:18 <edwardk> where extracting is forcing the future | |
00:48:25 ? Spion (~spion@unaffiliated/spion) quit: Ping timeout: 260 seconds | |
00:48:32 <edwardk> and extending builds a more complicated future | |
00:48:49 <edwardk> this is particularly nice for parallel code | |
00:49:03 ? kmels ([email protected]) quit: Ping timeout: 245 seconds | |
00:49:14 <edwardk> you wind up needing a 'strong lax semimonoidal comonad' in order to combine them though | |
00:49:44 <edwardk> that is to say they need an operation like the ap <*> or |*| or whatever its called in scalaz from Applicative | |
00:50:01 <edwardk> where that operation is compatible with extract not return | |
00:50:08 <edwardk> (unit in scalaz) | |
00:50:27 <edwardk> an example of a comonad like that which is less scary is one i often use in parsers | |
00:50:40 <edwardk> say you are parsing a function body, and you want to know what variables you have bound in scope | |
00:50:47 <edwardk> you can pass them around in a comonad | |
00:51:19 <trepidacious_> Just quickly... in extends, you are creating Pointers that have the index at each element in turn, then applying f to each one | |
00:52:19 <trepidacious_> But each input Pointer to f just yields the single new element for the resulting Pointer | |
00:52:31 <jamil_1> edwardk: so....why is it that functors and cofunctors are same but monad and comonad are not (from the posted pdf link) | |
00:52:34 <edwardk> case class Patterned[A](extract: A, bound: List[Var]) { def ++[B](p: Patterned[B]) : Patterned[(A,B)] = Patterned((extract,p.extract), bound ++ p.bound); def extend[B](…) } | |
00:52:40 › xlorm ([email protected]) joined | |
00:52:55 <edwardk> jamil_1: functor = cofunctor just happens when you flip around the arrows you happen to get something with the same shape | |
00:53:07 <edwardk> there are 'contravariant' functors but there isn't a useful notion of a contravariant monad/comonad | |
00:53:18 <edwardk> trepidacious_: yep | |
00:53:53 <edwardk> a fun (infinite) variation is to work out the extend for Store | |
00:54:12 <edwardk> where instead of an array you are taking a function and making a new function | |
00:55:47 <trepidacious_> So, now I have something like a clue about one instance of a comonad, I at least have a chance of looking at the more general stuff | |
00:56:09 <edwardk> the main thing to think about is that the 'shape' of a comonad is invariant. you are just redecorating it | |
00:56:29 <edwardk> you may have to do some funny things to get all the other comonadic 'views' you need for each position | |
00:56:40 <trepidacious_> In the same way as for a monad, where the basic pattern is the same? | |
00:56:45 <edwardk> but overall you're just going to stitch together a bunch of versions of the data you already have | |
00:56:47 <edwardk> yeah | |
00:57:26 <edwardk> with a monad you take all your values, get new copies, and stitcht hem together, here we take all the positions, get a modified comonad that 'features' that position correctly and then we use the function to get their replacements | |
00:59:02 <trepidacious_> So the Pointer comonad features a position via the value of the index? | |
00:59:18 <trepidacious_> and when you say a modified comonad you are using "comonad" to refer to an instance of Pointer? | |
00:59:39 <edwardk> yeah, i should say 'comonadic value' | |
00:59:44 <edwardk> or some such | |
00:59:56 <edwardk> also notice that comonads work much nicer in scala than monads do | |
00:59:57 <trepidacious_> I guess in most cases the name of the comonad and the comonadic value are the same, like Option the type and Option the monad? | |
01:00:36 <edwardk> because you don't have to dispatch everything through implicits you can just bolt extend, extract, map, etc. as members | |
01:00:36 <edwardk> well, we can have a comonad where you have multiple constructors | |
01:00:40 ? szeiger ([email protected]) quit: Ping timeout: 260 seconds | |
01:00:47 <trepidacious_> Yeah it confuses me when reading about monads that scala uses different functions, and doesn't have an actual trait | |
01:01:18 › dbgster ([email protected]) joined | |
01:02:05 <edwardk> abstract class Stream[A] { def extract: A, def extend(…); def map(…) } case class Last[A](extract: A) extends Stream[A] { … }; case class Cons[A](extract: A, tail: Stream[A]) extends Stream[A] { … } | |
01:02:18 <trepidacious_> The Lens paper talks about map and coFlatMap, are they just derived from the extract and extend functions? | |
01:02:34 <edwardk> coFlatMap = extend, | |
01:02:50 <edwardk> i just have a different vocabulary than the author there | |
01:02:59 <edwardk> what Lens paper? | |
01:03:03 <trepidacious_> Yup I just wanted to check, like with bind/flatMap etc. | |
01:03:12 <trepidacious_> http://dl.dropbox.com/u/7810909/media/doc/lenses.pdf | |
01:03:38 <trepidacious_> That's what started me on this, I was following it right up to the comonads appeared ;) | |
01:04:33 <edwardk> i wrote the scalaz lens implementation which doesn't use store, and the data-lens library in haskell which does, so its funny seeing both in a paper | |
01:04:52 <trepidacious_> Ah cool | |
01:05:09 <edwardk> i don't like the partial lenses though | |
01:05:12 <edwardk> never have | |
01:05:24 <edwardk> i can't get my head around the bastardized version of the laws they require | |
01:05:36 <trepidacious_> I've been writing a mutable reactive programming system (Var[T], etc.), and I wanted to see how it would translate into immutable case classes, Lenses etc. | |
01:05:51 <edwardk> we use lenses for a lot of our code here at clarifi | |
01:06:05 <edwardk> we have big immutable states we carry around and use lenses to edit them | |
01:06:19 <edwardk> it was pretty much the first thing i wrote when i got here, which is why scalaz picked up lenses in the first place ;) | |
01:06:20 <trepidacious_> Yes that was the idea | |
01:06:28 <trepidacious_> Cool :) | |
01:06:47 <trepidacious_> My main interest is in GUIs, and binding | |
01:07:40 <trepidacious_> I was interested in producing a kind of persistent GUI, where images of bits of data are composited and only redrawn when the underlying data changes, if that makes any sense | |
01:08:12 <trepidacious_> I still haven't seen a nice immutable GUI type thing, so I thought I'd have a go | |
01:08:41 <edwardk> i need to port my revision control monad to scala, that makes that sort of thing really easy | |
01:08:57 <trepidacious_> Yeah whenever I think about these things, I am reminded of revision control | |
01:09:38 <trepidacious_> But the thing I don't understand is that there is so much work done on these things, but I've never run into a library that will take relatively sane looking code and make a nice GUI from it :) | |
01:09:50 <edwardk> http://research.microsoft.com/pubs/150180/oopsla065-burckhardt.pdf is probably a more accessible presentation than the one i use | |
01:10:15 <edwardk> in particular the 'incremental' part is what makes what you want go | |
01:11:36 › stephenjudkins ([email protected]) joined | |
01:11:56 <trepidacious_> Thanks | |
01:12:09 <trepidacious_> This is the stuff I want to duplicate (more or less): https://github.com/trepidacious/boxes | |
01:12:30 <trepidacious_> It works fine, but I keep thinking I should try to get rid of the mutability :) | |
01:12:39 <mapreduce> edwardk: Not a monad, and not Scala, but: https://github.com/rickyclarkson/inmemgit/blob/master/src/test/java/inmemgit/InMemGitTest.java | |
01:12:51 <mapreduce> That was fun to write but ultimately useless so far. :) | |
01:13:05 <edwardk> cute. very different from the code i'm talking about =) | |
01:13:33 ? AlbireoX`Laptop ([email protected]) quit: Remote host closed the connection | |
01:14:32 <jamil_1> case class Store[S,A](f: S => A, s: S) { def extends(g: Store[S,A] => B, st: Store[S,A]): Store[S,B] = Store( ss => g(st) , s ) } like this ? | |
01:14:45 <edwardk> basically the monad lets you specify 'revision controlled variables', where you make up a variable with an initial value and specify a three-way merge strategy for it, and you can then fork and join in the monad, where each time you fork, each fork gets effectively independent copies of the variables, and when you join if both branches edited the value, then the merge strategy is employed using the two new versions and their lowest comm | |
01:14:45 <edwardk> ancestor | |
01:15:19 <edwardk> wrong state in the internal one i think | |
01:15:49 <edwardk> also if you make extend a member of Store[S,A] you don't need to pass in another | |
01:15:52 <edwardk> just use this | |
01:16:02 <jamil_1> oh right | |
01:16:11 <trepidacious_> edwardk: For parallel operations, like an STM? | |
01:16:52 <edwardk> trepidacious_: except you have deterministic fork and join which ST doesn't give you, and you 'roll forward' merging results on conflict, you don't roll back | |
01:17:08 <trepidacious_> Sounds good :) | |
01:17:23 <mapreduce> Ah, now that sounds interesting. | |
01:17:32 <mapreduce> How do you deal with conflicts you can't resolve automatically? | |
01:17:38 <edwardk> the part where it becomes relevant to you is you can break the version control metaphor and add a new operation in addition to making variables, reading/writing, forking and joining | |
New messages | |
01:18:20 <edwardk> mapreduce: the ability to resolve conflicts is the job of the merge function, if you can't make a merge function, don't use versioned variables for it, and then you can't fork anything where you need to edit that variable in bad ways | |
01:18:41 <trepidacious_> The writing is presumably not actual mutation, it produces new "revisions"? | |
01:18:54 <edwardk> making a versioned variable with a merge function is you claiming you have reasoned about the global invariants | |
01:18:59 <edwardk> yeah | |
01:19:08 <dibblego> oh hi | |
01:19:26 <edwardk> i actually improved the known asymptotic bounds on online lowest common ancestor search as a side-effect of my research in this area ;) | |
01:19:28 <edwardk> heya dibblego | |
01:20:19 <edwardk> trepidacious_: the metaphor breaking operation you can add is a 'record' function | |
01:20:25 ? stephenjudkins ([email protected]) quit: Quit: stephenjudkins | |
01:20:37 <edwardk> which takes Rev[A] => Rev[(A,Rev[A])] | |
01:20:57 <edwardk> that is to say it computes the answer, and gives you an 'optimized' version of the revision control action for subsequent use | |
01:21:31 <edwardk> if you view the fork/join graph as a series of operations performed with a set of dependencies for each segment, the idea is to look at what variables have been edited since the first run, to see if you can just recycle the anwer | |
01:22:01 › stephenjudkins ([email protected]) joined | |
01:22:09 <trepidacious_> To avoid recalculating values if their dependencies don't change? | |
01:22:19 <edwardk> that way if you do something like a big parallel sum over a versioned array by forking down to a usable grain size, summing, and then joining the answers, you can recycle the paths where you didn't change the inputs | |
01:22:25 › SethTisue ([email protected]) joined | |
01:22:25 <edwardk> yep | |
01:22:29 <edwardk> now take your screen state | |
01:22:32 <edwardk> and version it | |
01:22:33 <trepidacious_> YEs that was the idea with the GUI | |
01:22:48 <edwardk> =) | |
01:23:08 <trepidacious_> Yup, so for example editing a "property" of an object would be cheap, because you only redraw the tile that deals with the edited property, etc. | |
01:23:37 ? bootcode ([email protected]) quit: Read error: Connection reset by peer | |
01:23:50 <trepidacious_> Combining that with tiles as textures and hardware accelerated compositing seems like it could be good :) | |
01:24:01 › bootcode joined ? plainflavored quit | |
01:24:33 <edwardk> =) | |
01:24:46 <edwardk> my work here is done. let me know when you have a full working implementation i can take indirect credit for | |
01:25:09 › jihedamine ([email protected]) joined | |
01:25:12 <trepidacious_> My current system steals the nice idea from another paper with mutable Var stuff, where a "Reaction" is monitored to see what other Vars it reads, and only applies the reaction when one of those changes, so I guess this is a very similar thing, but immutable | |
01:25:23 <trepidacious_> edwardk: You'd be welcome, thanks for the help :) | |
01:25:31 <mapreduce> That other paper sounds like FRP. | |
01:25:47 <trepidacious_> edwardk: My main interest is just in such a thing existing, so that I can use it to make apps ;) | |
01:26:11 <edwardk> i'll probably port it to scala at some point, but its hard to get enthusaistic about porting haskell code to scala | |
01:26:48 ? dbgster ([email protected]) quit: Quit: dbgster | |
01:26:48 <trepidacious_> Because of scala, or because porting code is boring? | |
01:27:22 <trepidacious_> I'm reluctant to move from scala because I feel like I've finally worked it out a bit, and Haskell seems very intimidating, but equally I've heard a lot of good things about Haskell | |
01:27:30 ? btby (~user@unaffiliated/btby) quit: Ping timeout: 260 seconds | |
01:27:50 <mapreduce> Haskell will probably improve your Scala. | |
01:27:51 <dibblego> I have a "port haskell to scala" battle-suit | |
01:28:00 <mapreduce> and might make a bunch of things make sense that don't right now | |
01:28:43 <trepidacious_> But is it ultimately a better language for the type of thing I'm doing? (In as far as I've explained what I'm doing?) | |
01:29:03 <trepidacious_> Mind you, that is probably a bad question | |
01:29:25 <dibblego> for learning? yes, far better | |
01:29:54 <trepidacious_> But not for actually implementing? | |
01:30:06 <dibblego> why wouldn't it be? | |
01:30:55 <trepidacious_> I don't know, that was what I was asking, and by qualifying the answer I thought you meant there were non-learning tasks scala might be better for :) | |
01:31:21 <dibblego> there are some things scala is more suited -- those things have the word "JVM" in the sentence | |
01:31:21 <trepidacious_> The thing I'm trying to do other than learn, is produce some kind of reactive programming system that can handle conventional looking GUI | |
01:31:50 <trepidacious_> Right, so basically interoperability with Java stuff is scala's one advantage? | |
01:31:52 <dibblego> for that, even if I was to end with scala, I'd start with haskell, to get rid of all the mistakes | |
01:31:57 <dibblego> yes, one | |
01:32:45 <mapreduce> There are a lot more programmers closer to being able to work with Scala without much retraining than being able to work with Haskell. | |
01:32:53 <mapreduce> So it's less scary for your corporation too. | |
01:33:05 › hiratara ([email protected]) joined | |
01:33:17 <trepidacious_> Hm, still makes my head hurt though :) I think the thing that gets me about Haskell is maybe not even the language at all, just that everything I find to read about it is aimed at people with much more maths/time/brains than me | |
01:33:17 <dibblego> I don't buy that, but I know many people do | |
01:33:24 <dibblego> so I can exploit those people, which is an advantage | |
01:33:39 <trepidacious_> So I find it hard to read anything/learn anything in Haskell | |
New messages | |
01:34:02 <dibblego> trepidacious: it's aimed at children -- try it | |
01:34:07 › looopy ([email protected]) joined | |
01:34:09 <mapreduce> trepidacious_: Well, maybe they just don't blog about simple stuff, but you'll probably find that once you've got some stuff down it's ok. | |
01:34:30 ? xiliax ([email protected]) quit: Remote host closed the connection | |
01:34:31 <dibblego> it will never be simple -- perhaps you're just used to the illusion that programming is not hard | |
01:34:35 <trepidacious_> dibblego: That means nothing, there are MANY children who are much smarter and more mathematically inclined than me | |
01:34:46 <dibblego> trepidacious: that was my point; it means nothing | |
01:35:24 <trepidacious_> dibblego: No that's not what I meant. I mean that the basics for discussion of Haskell are much higher than they are for other languages, which is a bit of a barrier to entry | |
01:36:06 <trepidacious_> mapreduce: Yup probably, but its like a ladder that starts at about 10 feet up - some people can probably jump up to it, I've tried a few times and failed ;) | |
01:36:19 <dibblego> but they are not | |
01:36:29 <dibblego> there is no "higher barrier" | |
01:36:48 <dibblego> the best bit about that is that if/when you work that out, you get to laugh at yourself, which is fun | |
01:37:08 <mapreduce> Use it as a calculator for a bit. :) | |
01:37:12 <mapreduce> @quote posh | |
01:37:12 <lambdabot> ricky_clarkson says: Sorry, I only use Haskell as a posh calculator. | |
01:37:16 › AlbireoX`Laptop ([email protected]) joined | |
01:37:25 <trepidacious_> dibblego: I've talked to you enough times (and it's been very helpful, thank you) to know that what you consider a barrier to entry and what I consider one, are very different things ;) I think you just can't see things from my level ;) | |
01:37:37 ? AlbireoX`Laptop ([email protected]) quit: Remote host closed the connection | |
01:37:46 <dibblego> ok, and you are free to keep thinking that, and you are free to keep being wrong and not getting it and that is fine -- I lose nothing | |
01:37:59 <dibblego> well, I potentially lose the library that edwardk wants | |
01:38:13 <dibblego> it must be me right? | |
01:38:47 <edwardk> trepidacious_: mostly because of scala's limitations | |
01:38:54 <trepidacious_> dibblego: The thing is, since using scala a bit, I feel like some of the stuff that I used to consider very hard to understand now seems simple, and I think there is a LOT more stuff like that I still need to understand that you obviously consider simple too. But just because I find it simple now, doesn't mean I can't remember the pain of trying to work it out ;) | |
01:39:17 <dibblego> by the way, I find it funny when confused people start talking about "levels" | |
01:39:20 <dibblego> sorry | |
01:39:46 <dibblego> trepidacious: that's the thing, *nothing* is simple and the thing for you work out, is that it will *always* be that way | |
01:39:54 <trepidacious_> dibblego: Level of understanding/knowledge/experience | |
01:39:59 <dibblego> I do see it from your perspective, you just haven't worked it out yet | |
01:40:07 <trepidacious_> hm, I'm not convinced ;) | |
01:40:11 <dibblego> and I will wait patiently for that to change, so I can have that library | |
01:40:17 <trepidacious_> heh ;) | |
01:40:40 <trepidacious_> I think I do have a point though, if probably not the one I seem to be jabbering about | |
01:41:17 ? hiratara ([email protected]) quit: Remote host closed the connection | |
01:41:17 <trepidacious_> A page on Haskell will talk about monads, categories, monoids, etc. A page about Scala is a bit more likely to just set down to an example of some kind of common task and hwo to do it. | |
01:41:21 <dibblego> it's an anxiety disorder for which I have no cure | |
01:41:23 <trepidacious_> I don't think either one is right or wrong | |
01:41:37 <trepidacious_> but I do know that the scala page can be followed with less terminology, generally | |
01:41:51 <trepidacious_> the terminology is very useful, but still gives a barrier to entry while I comb wikipedia again | |
01:41:56 <trepidacious_> that was all I meant | |
01:41:57 <dibblego> yes, Scala can make concepts harder to understand, unnecessarily | |
01:42:38 <trepidacious_> maybe ultimately, but I'm not sure everyone can start from the abstract concept without a concrete example | |
01:42:59 › ivan____ ([email protected]) joined | |
01:43:14 <dibblego> it doesn't work either way, because it is an anxiety disorder | |
01:43:31 <trepidacious_> Hm? Not knowing what a monad is, is an anxiety disorder? | |
01:43:36 <dibblego> nope | |
01:43:47 <trepidacious_> That actually makes a lot of sense, most people I know are anxious :) | |
01:43:53 <trepidacious_> I put it down to the economy | |
01:44:10 <dibblego> one day you will realise "monoid" is actually much easier to understand than some garbled piece of paper with scala all over it | |
01:44:27 <dibblego> and then you will say, "gee I was being a dick head, maybe I should ease up on the anxiety" | |
01:44:32 <trepidacious_> heh | |
01:44:33 <dibblego> and then you'll repeat this over and over | |
01:44:39 <dibblego> and then the anxiety disorder will disappear | |
01:44:50 <mapreduce> @type Monoid | |
01:44:51 <lambdabot> Not in scope: data constructor `Monoid' | |
01:44:54 <dibblego> and we will sit at the pub and say, "remember when you were scared of the word monad, yeah lol!?!!" | |
01:45:00 <mapreduce> @type Monad | |
01:45:01 <lambdabot> Not in scope: data constructor `Monad' | |
01:45:06 <mapreduce> :t Monad | |
01:45:07 <lambdabot> Not in scope: data constructor `Monad' | |
01:45:07 <dibblego> I can do nothing until that day, because I have no cure | |
01:45:10 <mapreduce> argh | |
01:45:13 <mapreduce> that used to work | |
01:45:32 <dibblego> writing garbled scala on a piece of paper and saying, "yeah this is the real shit" is just an illusion -- an appeasement of the disorder that helps nobody | |
01:45:33 <trepidacious_> The thing is though... if I have looked at a page about Monads several times, read the explanation, diverted into an (infinite?) descent through Wikipedia pages about it, then given up, how does that help me learn? | |
01:45:49 <dibblego> you're already ill-prepared to learn, with that anxiety | |
01:45:52 <trepidacious_> But now I can (more or less) read the same pages, and have half a clue what they are talking about | |
01:46:05 <dibblego> imagine retracing those steps without it | |
01:46:34 <dibblego> I saw a really good example of this issue recently by the way | |
01:46:41 <dibblego> http://meta.stackoverflow.com/questions/134333/how-to-avoid-scaring-off-beginners-with-advanced-answers | |
01:46:49 <trepidacious_> and the intervening stage wasn't just manning up and magically understanding, it was using some monads in scala, and building up some kind of mental framework and familiarity that then gave the abstract explanation somewhere to settle in my confused mind ;) | |
01:46:55 <dibblego> the "layers of wrong" here are quite startling | |
01:47:13 <dibblego> why did that take you longer than 5 minutes? what were you doing the other time? | |
01:48:39 <trepidacious_> Reading the article, encountering a term I didn't know, looking up that term, encountering a term I didn't know, etc. | |
01:48:49 ? bootcode ([email protected]) quit: Ping timeout: 252 seconds | |
01:49:07 <trepidacious_> Not having an intrinsic ability to understand the full implications flowing from an abstract concept without having my hand held as some of those implications were spelt out? | |
01:49:19 › hiratara ([email protected]) joined | |
01:49:31 <trepidacious_> Just plain not being at a level of understanding where the things that are interesting and comprehensible to Haskell bloggers are the same to me? | |
01:49:51 <trepidacious_> Like gears in a car... 5th gear is an awesome gear, but not for pulling away | |
01:50:29 <trepidacious_> An article that reiterated every simple concept in order to get to the more complex concepts and be a complete how to guide... that would be a LONG and boring article for the people who actually wanted to read about the advanced stuff | |
01:50:53 <mapreduce> You need a directed acyclic graph that gets you from what you know to what you want to know. | |
01:50:56 <mapreduce> :) | |
01:51:03 <trepidacious_> But I can only find the complex articles, not the hand holding introduction ones - this isn't so much about Haskell as my ability to find the articles I should be reading, I guess ;) | |
01:52:05 <dibblego> that has to do with unfamiliarity of concepts, not haskell | |
01:52:12 <trepidacious_> Absolutely, yes | |
01:52:14 <dibblego> btw, programming is hard | |
01:52:18 <ivan____> trepidacious_: in the last 2 weeks ive just been googling a lot for articles, reading htem all even if i dont understand | |
01:52:34 <trepidacious_> None of this was meant to be against Haskell in any way, just an explanation of why I keep finding it hard to get into | |
01:52:41 <ivan____> and then im going back over them now and i understand more usually | |
01:52:52 <trepidacious_> Which as I say could be as much down to my poor googling as anything ;P | |
01:52:57 <dibblego> some people, when faced with this proposition, completely shit themselves and babble crap forever -- some suspend disbelief which I expect you are doing | |
01:52:58 ? hiratara ([email protected]) quit: Remote host closed the connection | |
01:53:43 <trepidacious_> dibblego: Well my current approach is m=pretty much what ivan____ is doing, combined with hacking away at scala because it can do some of this stuff, and I know roughly what the syntax and libraries look like now ;) | |
New messages | |
01:54:15 <dibblego> some people complain that "papers use haskell and this is unfamiliar" | |
01:54:27 <dibblego> when actually, haskell is so easy it is already familiar | |
01:54:41 <dibblego> but it's just programming concepts are unfamiliar | |
01:54:58 <trepidacious_> Yup, but the basic primers in those concepts seem hard to find, IMHO | |
01:55:05 <dibblego> I advise, get used to this -- the next will always be just as unfamiliar | |
01:55:06 <trepidacious_> at least in haskell, less so in scala | |
01:55:07 <ivan____> yeah ive started to read more haskell docs now that its sorting itself out in my head | |
New messages | |
01:55:41 <dibblego> however, those who complain loudest feel threatened by the prospect that "programming is hard" and "basic programming concepts are unfamiliar to me" | |
01:55:46 <ivan____> being able to read function sigs in haskell seems to go a long way heh | |
01:55:46 <apeshimam> trepidacious_: Im nowhere near an expert in many of the concepts you've mentioned but I do find the simplicity with which haskell presents concepts much easier to consume than scala | |
01:55:50 <trepidacious_> I can now follow the definitions of monads, etc. in Haskell, because the concept of first class functions is a bit more familiar. | |
01:55:53 <dibblego> just don't be one of those and you'll be fine | |
01:56:20 <mapreduce> :t fix | |
01:56:21 <lambdabot> forall a. (a -> a) -> a | |
01:56:50 <mapreduce> Things like that mess with my head. | |
01:56:51 <pfurla> dibblego: i admit to these quotes myself despite not feeling threatened | |
01:56:59 <trepidacious_> It really isn't so much about the language as the available learning materials, for me... I agree that scala as a language seems VERY complicated, although the subset required to do a lot of interesting stuff seems much smaller. Equally the bits of Haskell I've understood seem very elegant | |
01:57:55 <apeshimam> so beyond blog posts what have you tried? a lot of this is determining what style of learning works for you, IMO | |
01:58:57 › voidcoder ([email protected]) joined | |
01:59:08 <trepidacious_> dibblego: I know what you mean - for example it seems one reason that people won't try something new (like scala say), is that they feel stupid when they don't understand something, and that is inevitable when looking at a different programming "model". I'm allowing for that, I felt fairly dumb when learning scala, so I'll allow the same process for Haskell. | |
01:59:33 ? voidcoder ([email protected]) quit: Read error: Connection reset by peer | |
01:59:39 <trepidacious_> dibblego: My problem is not so much feeling stupid or threatened in my insular imperative ways, as just not managing to work out what the words mean, but I'll keep giving it a go ;) | |
02:00:03 › voidcoder ([email protected]) joined | |
02:00:05 <dibblego> then you will get there, slowly at first | |
02:00:45 ? ornicar ([email protected]) quit: Ping timeout: 260 seconds | |
02:01:02 <mapreduce> I felt more stupid when facing Crystal Reports and stored procedures than Haskell or Scala have ever made me feel. | |
02:01:09 <trepidacious_> dibblego: Yup. Maybe I should put my money where my mouth is, and actually try to document the process, at the very least I could try to put some basic concepts in the order someone might want to approach them. I'm surprised no one else has, I'd love to know how people learn Haskell from scratch :) | |
02:01:25 <dibblego> try telling someone else what monad means | |
02:01:39 <qU1j0t3> dibblego | for that, even if I was to end with scala, I'd start | |
02:01:41 <qU1j0t3> with haskell, to get rid of all the mistakes | |
02:01:44 <mapreduce> because I didn't know how to take that next step towards understanding more, which always seems to be visible in Haskell or Scala. | |
02:01:49 ? voidcoder ([email protected]) quit: Read error: Connection reset by peer | |
02:02:05 <ivan____> trepidacious_: i dont really think you can help people learn it, since it wont make sense to someone that doesnt know - which is the whole problem i think | |
02:02:26 <trepidacious_> ivan____: Yeah, I know what you mean, although that seems like chicken and egg :) | |
02:02:46 <ivan____> what it means is there is no silver bullet, you just have to put in the hard work | |
02:03:01 › rbarraud ([email protected]) joined | |
02:03:05 <ivan____> i remember doing the same thing when i first started programming | |
02:03:14 <ivan____> i was always totally confused | |
02:03:15 <ivan____> lol | |
02:03:46 <trepidacious_> ivan____: No silver bullet, but... Ok an example - when I was looking at monads, I found a page that spelt out the exact names used for each function in each language (most importantly haskell and scala) and gave some examples. It was harder work finding that than if someone had pointed me at it | |
02:03:47 <pfurla> mapreduce: ergh, only had bad experiences of crystal :/ | |
02:03:54 <mapreduce> Me too. | |
02:03:54 <pfurla> s/of/with | |
02:04:09 <trepidacious_> ivan____: The whole reading/understanding thing can't be done for you, but a nice tour of some pages that make sense and fit together will help a LOT :) | |
02:04:42 <dibblego> C# has monads built right in to the language, but nobody seems to notice -- possibly because the implementation is quite degenerate | |
02:04:51 <ivan____> my biggest problem is applying what i learn to my own problems | |
02:05:04 <mapreduce> People notice C#'s monads. | |
02:05:12 <ivan____> i can read and even somewhat understand other peoples examples | |
02:05:13 <dibblego> they didn't when I last checked | |
02:05:26 <dibblego> I once told #csharp that monads were in their language and they got very upset | |
02:05:30 <pfurla> actually i don't even think i really used it, the company i worked for only used it to generate pdfs and have easy "print' buttons everything else was text based :/ | |
02:05:46 <trepidacious_> dibblego: I think after people have used those for a while, they might be more likely to understand the general concept though. Then I agree, you probably need to tweak their understanding a bit, but you have somewhere to start ;) | |
02:06:01 <mapreduce> One of the ##csharp regulars ported a good chunk of Haskell's prelude to C#. | |
02:06:20 › voidcoder ([email protected]) joined | |
02:06:22 <ivan____> dibblego: it seems to be that people get upset as soon as they here it because of the brainwashing - same thing when i hear people talk about scala's "academics" | |
02:06:28 <dibblego> maybe they figured it out by now -- this was years ago | |
02:06:45 <mapreduce> 3 years ago I joined for the first time. | |
02:07:08 <edwardk> mapreduce: works well until you start wanting to do something like use a function polymorphic in the choice of monad, etc. | |
02:07:10 › jcazevedo ([email protected]) joined | |
02:07:24 <trepidacious_> I was very impressed that there's a nice browser based Haskell REPL thingy and some tutorials now, it's going in the right direction. I was just sad when I ran out of tutorials | |
02:07:25 <mapreduce> edwardk: LINQ? Yes, the monad is statically decided. | |
02:07:45 <dibblego> sequenceList, sequenceMaybe, sequenceReader, sequenceState | |
02:07:59 <edwardk> mapreduce: yeah, i die a little inside every time i have to write the same code to work with the reactive framework and some other linq provider | |
02:08:05 <mapreduce> Is Scala better that way? | |
02:08:16 <dibblego> sure, it has TC polymorphism | |
02:08:30 <dibblego> for-comprehensions are not though | |
02:08:30 <edwardk> mapreduce: yes, you can write code that is parametric in higher kinded types | |
02:08:39 <mapreduce> after all, flatMap/foreach/filter/map aren't actually part of a trait. | |
02:08:53 <mapreduce> or at least you don't need them to be to use for-comprehensions. | |
02:09:02 <dibblego> wouldn't it be nice? | |
02:09:03 <edwardk> mapreduce: no, but you can be parametric in some M, and use a scalaz Monad | |
02:09:19 <dibblego> trait Bind[F[_]] { def map... def flatMap... } | |
02:09:40 <edwardk> for comprehensions are so awful that i spent a week or so _removing_ monads from a large swath of code at work | |
02:10:30 <trepidacious_> Well, thanks again for help, 1AM is probably too late to be trying to think straight... I'll let you all know when I get my super-gui library going ;) | |
02:10:34 <edwardk> dibblego: http://hpaste.org/68398 is the set of trait mixins we use here | |
02:10:35 <dibblego> edwardk: btw, have you written the partial lens laws out? | |
02:10:41 <edwardk> dibblego: i did at some point | |
New messages | |
02:10:49 <dibblego> yeah me too, and got a bit tangled up | |
02:10:58 <edwardk> they are (Store s :+: Id) comonad coalgebras | |
New messages since you scrolled up | |
02:11:00 <edwardk> easy ;) | |
02:11:09 <edwardk> this is why i hate partial lenses | |
===================================== | |
21:16:20 <Apocalisp> for that you should use the comonad | |
21:16:40 <atoll> what do you mean ? | |
21:16:46 <Apocalisp> extend it with a function that takes a tree and turns it into the pair | |
21:16:51 <atoll> (i mean the comonad is the treeloc no ?) | |
21:16:58 ? noelw ([email protected]) quit: Quit: noelw | |
21:17:04 <Apocalisp> no, both Tree and TreeLoc are comonads | |
21:17:20 <atoll> ? | |
21:17:31 <Apocalisp> TreeLoc is a zipper on the Tree, but Tree by itself is also a comonad | |
21:17:37 <atoll> of what ? | |
21:17:44 <atoll> of A ? | |
21:17:47 › ornicar joined ? RSchulzM quit | |
21:18:05 <lizzin> d_m: are you familiar with mongo | |
21:18:05 <lizzin> ? | |
21:18:46 › zer ([email protected]) joined | |
21:18:46 <d_m> lizzin: no, i've never used it. | |
21:18:51 › _eclark joined ? kjetilv quit | |
21:18:53 <Apocalisp> atoll: What do you mean of what? | |
21:19:06 <atoll> well Tree is the comonad of what | |
21:19:13 <d_m> i've heard a wide variety of opinions on it though. as far as your problem, it almost sounds like your client is connecting to the wrong server or something. | |
21:19:16 › kjetilv ([email protected]) joined | |
21:19:22 <Apocalisp> atoll: There exists a Comonad[Tree] | |
21:19:28 <d_m> or maybe you aren't replicating the data, or aren't saving it properly or something... *shrug* | |
21:19:35 <Apocalisp> atoll: As well as Comonad[TreeLoc] | |
21:19:51 <atoll> well Comonad[Tree] is TreeLoc no ? | |
21:19:58 <Apocalisp> atoll: no | |
21:20:20 ? arussel ([email protected]) quit: Ping timeout: 248 seconds | |
21:21:05 <lizzin> hrmm | |
21:21:49 › noelw ([email protected]) joined | |
21:22:16 <atoll> but if TreeLoc is the zipper of tree, it's his comonad no ? | |
21:22:31 ? kushal (~kdas@fedora/kushal) quit: Read error: Operation timed out | |
21:23:44 <Apocalisp> Do you understand what a comonad is? | |
21:24:00 <atoll> not totally but i think | |
21:24:03 ? scorphus (~scorphus@CAcert/User/scorphus) quit: Quit: Leaving | |
21:24:31 <Apocalisp> Comonad is an interface with two methods. | |
21:24:54 <atoll> copoint and i forgot the other one | |
21:25:07 <Apocalisp> extend | |
21:25:10 <Apocalisp> or cobind | |
21:25:16 <Apocalisp> I forget which it's called | |
21:25:27 <FurnaceBoy> wow, if YOU forget what hope is there for we mortals :-< | |
21:25:43 <Apocalisp> but the type of cobind is (W[A] => B) => W[A] => W[B] | |
21:25:53 <Apocalisp> FurnaceBoy: The type is what's important :) | |
21:26:00 <FurnaceBoy> :) | |
21:26:02 › RSchulzM ([email protected]) joined | |
21:26:04 <FurnaceBoy> Apocalisp: j/k. | |
21:26:21 <atoll> i call it reverse flatmap | |
21:26:34 <Apocalisp> it's the dual of flatMap | |
21:27:06 <Apocalisp> anyway, you can get a tree with all of the treelocs in it | |
21:27:20 <Apocalisp> tree.cobind(t => (t.loc, t)) | |
21:27:45 <atoll> i dont understand how it works but thanks | |
21:28:03 <Apocalisp> It will first construct a Tree of all the subtrees | |
21:28:18 <Apocalisp> then map the function over that tree | |
21:28:32 <Apocalisp> each tree will be turned into a pair of: itself and its loc | |
21:28:42 <atoll> a Tree of all the subtrees ? isn't that the normal tree ? | |
21:28:47 <Apocalisp> no | |
21:28:56 <Apocalisp> Tree[Tree[A]] | |
21:28:59 <atoll> oh | |
21:29:02 <atoll> ok | |
21:29:13 <Apocalisp> Where each Tree in the outer tree is the full subtree from that node down | |
21:30:02 ? noelw and RSchulzM quit | |
21:30:35 <Apocalisp> it's like tails | |
21:30:40 <Apocalisp> ! List(1,2,3).tails | |
21:30:41 <multibot_> Iterator[List[Int]] = non-empty iterator | |
21:30:42 › futurechimp and dspanks_ joined | |
21:30:48 <Apocalisp> oh well | |
21:30:59 <Apocalisp> it's a list of all the sublists | |
21:31:02 <Apocalisp> well, tails | |
21:31:48 › kjetilv1 joined ? blooo and headius quit | |
21:32:36 <atoll> i maybe understand it wrong but will it not create the treeloc of each subtree instead of the treeloc of the node with focus on the subtree ? | |
21:32:50 › blooo ([email protected]) joined | |
21:33:14 <Apocalisp> oh yeah, you're right | |
21:33:18 <Apocalisp> ok, so... | |
21:33:20 ? kjetilv and dspanks quit | |
21:33:40 <Apocalisp> tree.loc.cobind(t => (t.toTree, t)).toTree | |
21:33:44 › blackrain joined ? SHODAN quit Arr`Gone › Arrgh | |
21:35:34 <atoll> oh nice | |
21:35:36 › SHODAN, lnostdal_, RSchulzM and blooo_ joined | |
21:39:15 <Apocalisp> of course, a TreeLoc always lets you get the subtree under focus | |
21:39:56 <Apocalisp> so tree.loc.copoint.toTree does the same thing, essentially | |
New messages | |
21:40:37 <Apocalisp> comonads are pretty awesome | |
21:40:48 ? blooo and sbenthall quit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment