Cale 2017-01-31 00:45:13
^^ stuff like this can be pretty cute at times
roxxik 2017-01-31 00:46:37
ski: i did that with other stuff, just found out about exference bot and i'm wondering where the difference between the two versions is
ski 2017-01-31 00:46:46
in "Selection Functions, Bar Recursion, and Backward Induction" by Martín H. Escardó,Paulo Oliva in 2009-11-11 at , they do "products" of quantifiers, like Cale is alluding to, for reasoning about games (game theory) .. iirc including infinite games
ski 2017-01-31 00:47:04
roxxik : there's also `djinn'
ski 2017-01-31 00:47:19
@djinn-add type NotNot a = Not (Not a)
ski 2017-01-31 00:47:34
@djinn NotNot (a -> b) -> (NotNot a -> NotNot b)
lambdabot 2017-01-31 00:47:34
f a b c = void (b (\ d -> void (a (\ e -> c (e d)))))
roxxik 2017-01-31 00:47:51
sure, but that does not change the result: there are two possible ways to implement <*> for Cont and i'm wondering why only one is used
ski 2017-01-31 00:49:14
(obviously you can do the version with a final answer / result type ⌜ω⌝ (your `r'), instead of an "uninformative" (in some sense with information content of ⌜-∞⌝) `Void' answer type)
merijn 2017-01-31 00:50:22
Cale: You're a math-y person! I have a problem which I'm fairly sure *someone* has solved, but I don't have a clue which terminology to use to search for it, if you have a sec to listen to my description and see if it rings any bell I'd be grateful
ski 2017-01-31 00:51:41
roxxik : given one sequential ordering, you can derive the other one by changing the ordering, in a similar way to how for a `Monoid' instance, you can get the opposite ordering by using `Dual'
ski 2017-01-31 00:51:45
> getDual (Dual (First (Just 2)) <> Dual (First (Just 3))) :: First Integer
lambdabot 2017-01-31 00:51:48
First {getFirst = Just 3}
ski 2017-01-31 00:52:26
roxxik : so it's about whether to first execute the first argument, or the second one
roxxik 2017-01-31 00:53:08
i just skimmed through the other one and saw that it's doing weird things with it's arguments...
roxxik 2017-01-31 00:53:34
`\f v c -> v \g -> f \h -> c (h g)`
Cale 2017-01-31 00:53:35
merijn: go for it
merijn 2017-01-31 00:53:39
Cale: So I have an N-dimensional space which I'm partitioning into a number of hypercubes (they're effectively bounding boxes of min/max pairs in each dimension). Now, given this I can pick a point in dimension D and compute the "cross-section" (i.e., which hypercube this plane bisects), and I would like to find out all the points where this crosssection "changes" (i.e., one of the hypercubes is no longer
merijn 2017-01-31 00:53:45
intersected or a new hypercube is intersected), preferably I'd like to compute these points for every single dimension
ski 2017-01-31 00:54:22
roxxik : for a monad, you have a dynamic dependency of the second on the first, so there's only one possibility there (well, for state, there's the "backwards-in-time" version, but you need to tie a knot to do that, and it's easy to fall down the bottom of the well, if you're not careful (still it can be careful, e.g. for automatic differentiation, iirc). anyway, afaik, there's no such thing for `Cont')
roxxik 2017-01-31 00:55:19
f :: (((a -> b) -> r) -> r), v :: ((a -> r) -> r), c :: (b -> r), g :: a -> r, h :: (a -> b) -> r (i inffered some stuff here myself, based on the lambda the variable is used in
ski 2017-01-31 00:55:35
roxxik : as i said, the two solutions exferenceBot gives are the two execution orderings (i just checked to make sure, but i was all but certain before foing that)
Cale 2017-01-31 00:55:41
merijn: like, the D-th projection of all the bounding coordinates of the hypercubes?
ski 2017-01-31 00:56:31
roxxik : for some reason, exferenceBot chose to obfuscate the second solution (iow first executing the action yielding the function), by using function composition ..
Cale 2017-01-31 00:56:32
merijn: well, wait, you said "plane"...
roxxik 2017-01-31 00:56:36
but what's the difference between the two solutions then? if ordering won't make a difference
Cale 2017-01-31 00:56:59
merijn: oh, no, I get what you mean there
merijn 2017-01-31 00:57:04
Cale: Maybe I'm describing things wrong, I'm generalising my own 3d intuition to >3 dimensions
Cale 2017-01-31 00:57:19
merijn: Yeah, seems like the Dth projection of the coordinates of the vertices of the cubes
roxxik 2017-01-31 00:57:20
ski: this is from transformers: f <*> v = ContT $ \ c -> runContT f $ \ g -> runContT v (c . g)
ski 2017-01-31 00:57:32
roxxik : so it's a choice between `\iab ia kb -> iab (\ab -> ia (\a -> kb (ab a)))' (the second solution exferenceBot gave) and `\iab ia kb -> ia (\a -> iab (\ab -> kb (ab a)))'
Cale 2017-01-31 00:57:37
merijn: they're axis-aligned, right? :)
ski 2017-01-31 00:57:57
roxxik : the former of these first executes `iab', then `ia'. the latter does the opposite order of execution
Cale 2017-01-31 00:58:03
Yeah, "min/max pairs in each dimension"
roxxik 2017-01-31 00:58:16
i saw that, i'm wondering what difference this makes
merijn 2017-01-31 00:58:21
Cale: Yeah
ski 2017-01-31 00:58:33
roxxik : that `ContT' version is the "first execute first/left argument" choice, which i think is reasonable as the "default"
Cale 2017-01-31 00:58:51
So, when you project along the Dth axis, your cross section always changes when you're hitting a vertex of some hypercube
ski 2017-01-31 00:58:56
roxxik : the difference is between executing left-to-right, or right-to-left
Cale 2017-01-31 00:59:12
Er, I could have worded that better
roxxik 2017-01-31 00:59:35
sure, but in a lazy language that difference won't matter. question is: can i use both versions interchangeable?
Cale 2017-01-31 00:59:35
As you select cross sections along the Dth axis
Cale 2017-01-31 01:00:02
So that'll be when you hit the min or max for one of the cubes in that direction.
Cale 2017-01-31 01:00:06
right?
merijn 2017-01-31 01:00:12
Cale: Right
ski 2017-01-31 01:00:19
roxxik : if `iab' in `iab <*> ia' expresses a universal quantifier, and `ia' an existential quantifier, then using left-to-right will express something of the shape `forall a. exists b. ..a..b..', while right-to-left will express something of the shape `exists b. forall a. ..a..b..' -- obviously these two are very different
roxxik 2017-01-31 01:01:15
oh
ski 2017-01-31 01:01:23
roxxik : "but in a lazy language that difference won't matter" is irrelevant. the language that `ContT' *expresses* is not that simple lazy language where order of execution doesn't matter. it definitely *does* matter !
roxxik 2017-01-31 01:02:03
i think i need some example to see how Cont behaves to understand this better...
ski 2017-01-31 01:02:17
roxxik : of course, we're expressing this *in* Haskell, and as Haskell expressions, it doesn't matter which order you *evaluate* (not execute) expressions (as long as you require the result of both)
roxxik 2017-01-31 01:02:33
yah
roxxik 2017-01-31 01:03:02
how can i "expresses a universal quantifier"?
ski 2017-01-31 01:03:39
roxxik : but just like you wouldn't think `do putStrLn "A"; putStrLn "B"' was the same as `do putStrLn "B"; putStrLn "A"', you shouldn't think `foo <$> ia <*> ib' is the same as `flip foo <$> ib <*> ia', in the case of `Cont'/`ContT' (or `State'/`StateT' or parsers, or ...)
merijn 2017-01-31 01:03:39
Cale: I was thinking of building an interval tree for each dimension and then storing, for each hypercube, it's range in the Dth dimension in its corresponding interval tree and then scanning for points where the set of intervals in the stabbing query changes, but I wasn't sure whether there's more sensible solutions
Cale 2017-01-31 01:05:05
Well, you can also just store the set of points
Cale 2017-01-31 01:05:55
(you probably need the intervals for other purposes, but it may for some purposes be more straightforward to lose them and just retain their endpoints)
ski 2017-01-31 01:05:58
@let forEach :: Foldable t => t a -> Cont Bool; forEach = cont . flip all
lambdabot 2017-01-31 01:06:04
.L.hs:166:33: error:
lambdabot 2017-01-31 01:06:04
• Expecting one more argument to 'Cont Bool'
lambdabot 2017-01-31 01:06:04
Expected a type, but 'Cont Bool' has kind '* -> *'
merijn 2017-01-31 01:06:05
hmmm
ski 2017-01-31 01:06:08
er, right
ski 2017-01-31 01:06:11
@let forEach :: Foldable t => t a -> Cont Boola ; forEach = cont . flip all
lambdabot 2017-01-31 01:06:13
.L.hs:166:38: error:
lambdabot 2017-01-31 01:06:13
Not in scope: type constructor or class 'Boola'
lambdabot 2017-01-31 01:06:13
Perhaps you meant 'Bool' (imported from Data.Bool)
ski 2017-01-31 01:06:23
@let forEach :: Foldable t => t a -> Cont Bool a ; forEach = cont . flip all
lambdabot 2017-01-31 01:06:25
Defined.
ski 2017-01-31 01:06:27
@let forSome :: Foldable t => t a -> Cont Bool a; forSome = cont . flip all
lambdabot 2017-01-31 01:06:30
Defined.
ski 2017-01-31 01:06:49
@let evalCont :: Cont o o -> o; evalCont = (`runCont` id)
lambdabot 2017-01-31 01:06:51
Defined.
ski 2017-01-31 01:07:02
@let evalContT :: Monad m => ContT o m o -> o; evalContT = (`runContT` return)
lambdabot 2017-01-31 01:07:04
.L.hs:176:14: error:
lambdabot 2017-01-31 01:07:04
• Couldn't match type 'o' with 'm o'
lambdabot 2017-01-31 01:07:04
'o' is a rigid type variable bound by
ski 2017-01-31 01:07:11
@let evalContT :: Monad m => ContT o m o -> m o; evalContT = (`runContT` return)
lambdabot 2017-01-31 01:07:13
Defined.
ski 2017-01-31 01:08:23
> evalCont (do x <- forEach [0,2,3,5]; y <- forSome [2,5,6]; return (x < y))
lambdabot 2017-01-31 01:08:27
False
ski 2017-01-31 01:09:05
sorry, that should be
ski 2017-01-31 01:09:09
> evalCont (do x <- forEach [0,2,3,5]; y <- forSome [2,5,6]; return (x < y))
lambdabot 2017-01-31 01:09:12
True
ski 2017-01-31 01:09:24
(`forSome' should of course use `any', not `all')
ski 2017-01-31 01:10:22
> evalCont (do x <- forEach [0,3,5]; y <- forSome [1,2,3,4,6]; return (x + 1 == y))
lambdabot 2017-01-31 01:10:25
True
ski 2017-01-31 01:10:34
> evalCont (do y <- forSome [1,2,3,4,6]; x <- forEach [0,3,5]; return (x + 1 == y))
lambdabot 2017-01-31 01:10:37
False
ski 2017-01-31 01:10:55
for each `x' in the given list, there's an `y' which is the successor of it
ski 2017-01-31 01:11:09
but there's not single `y' which is simultaneously the successor of all the `x's
ski 2017-01-31 01:11:27
roxxik : so that's a trivial example of when the ordering matters
simli 2017-01-31 01:18:29
I have some problems doing network communication with conduit, specifically combining it with protobuf and cereal-conduit
simli 2017-01-31 01:19:25
symptom is that about 50% my (simple) test works just fine, but the other half the connection closes before the server has read what it "should" have read
simli 2017-01-31 01:20:09
trying to figure out what is happening, I turned to the strace tool only to find that very little relevant information is printed
simli 2017-01-31 01:20:39
is there some trick to using strace with haskell programs? Or some other tool I can use to see what is going on?
merijn 2017-01-31 01:20:59
simli: strace only shows syscalls, though, so I wouldn't expect that to show much
simli 2017-01-31 01:21:22
merijn: I was looking for networking syscalls to see errnos and such
merijn 2017-01-31 01:21:28
simli: Well, one relevant thing would be
merijn 2017-01-31 01:21:31
@quote oasis
lambdabot 2017-01-31 01:21:31
chromatic says: My productivity increased when Autrijus told me about Haskell's trace function. He called it a refreshing desert in the oasis of referential transparency.
merijn 2017-01-31 01:21:46
simli: i.e. Debug.Trace.traceM
merijn 2017-01-31 01:22:55
simli: Connection closing before the server has read what it should sounds like there might be a bug in your parser? But I'm not too familiar with conduit, so I can't say much
simli 2017-01-31 01:22:59
merijn: that's a funny quote :D
merijn 2017-01-31 01:23:44
simli: Debug.Trace is a great module to ease printf debugging (with the usual caveat being horribly unsafe for production)
simli 2017-01-31 01:24:30
merijn: Thing is I've barely implemented any logic myself, protobuf can (and do in my case) use generics to derive instances... That said I have an even simpler example that works better
merijn 2017-01-31 01:24:33
simli: I'm thinking maybe your conduit exits before consuming all data, resulting in the connection closing
simli 2017-01-31 01:25:01
so it's certainly possible I've made a mistake. So i need insight into what my code does, so... tool :)
merijn 2017-01-31 01:25:31
simli: instrumenting your conduit with traceM could help see where it's terminating
simli 2017-01-31 01:25:50
merijn: I'll have a look at that for sure!
roxxik 2017-01-31 01:29:38
ski: i'll type those into my repl and see if i can make sense of the alternative <*> implementation, but thanks for the example
ski 2017-01-31 01:32:34
roxxik : i think there's something like `newtype Opposite i a = MkOpposite {runOpposite :: i a}' with `instance Applicative i => Applicative (Opposite i)' doing `i', but in the opposite order, but i'm not sure about the name, and in which package it would be
roxxik 2017-01-31 01:32:53
i'll search for it later
roxxik 2017-01-31 01:33:44
somethink like f <*> v = do { v' <- v; f' <- f; f v } ? (if it had a monad constraint)
roxxik 2017-01-31 01:34:00
return (f' v')
simli 2017-01-31 01:34:47
merijn: well reading some, I guess trace is a great tool to have, but most of my code actually has access to IO already. But get this, now I can't reproduce it anymore
ski 2017-01-31 01:34:59
roxxik : well, `MkOpposite iab <*> MkOpposite ia = MkOpposite <$> (flip ($) <$> ia <*> iab)' would probably be the simplest, readable, way of implementing it
ski 2017-01-31 01:35:18
roxxik : so, your basic idea was the right one, yes
simli 2017-01-31 01:35:25
scary race-like kind of problem, and it just vanishes. Also kind of like a race condition :S
roxxik 2017-01-31 01:36:09
hmm interesting... then it should always be possible to find an alternative Applicative ?
roxxik 2017-01-31 01:36:13
instance*
roxxik 2017-01-31 01:37:50
this would be the newtype wrapped cont: \f v -> cont $ \c -> runCont v $ \g -> runCont f $ \h -> c (h g)
roxxik 2017-01-31 01:37:54
:t \f v -> cont $ \c -> runCont v $ \g -> runCont f $ \h -> c (h g)
lambdabot 2017-01-31 01:37:56
Cont r (t -> a) -> Cont r t -> Cont r a
ski 2017-01-31 01:39:20
roxxik : compare with how `Dual' can be used, to get a `Monoid' instance with the opposite combination order,
roxxik 2017-01-31 01:39:58
yah
roxxik 2017-01-31 01:42:04
my alternative apply behaves exactly the same as the original apply
roxxik 2017-01-31 01:42:14
(at least for the forEach, forSome examples
roxxik 2017-01-31 01:43:26
no it doesn't
ski 2017-01-31 01:43:41
how's your alternative defined ?
thatguy 2017-01-31 01:43:52
I have downloaded hoogle and searches like "hoohle map" do return something, but "hoogle [a] -> a" doesn't return anything
roxxik 2017-01-31 01:43:55
@let altAp f v = cont $ \c -> runCont v $ \g -> runCont f $ \h -> c (h g)
thatguy 2017-01-31 01:43:56
does anyone know why?
lambdabot 2017-01-31 01:43:57
Defined.
roxxik 2017-01-31 01:44:14
> evalCont (((\x y -> x + 1 == y) <$> forEach [0,3,5]) `ap` forSome [1..6])
lambdabot 2017-01-31 01:44:17
True
roxxik 2017-01-31 01:44:23
evalCont (((\x y -> x + 1 == y) <$> forEach [0,3,5]) `altAp` forSome [1..6])
roxxik 2017-01-31 01:44:32
> evalCont (((\x y -> x + 1 == y) <$> forEach [0,3,5]) `altAp` forSome [1..6])
lambdabot 2017-01-31 01:44:35
False
ski 2017-01-31 01:44:53
looks fine, to me
ski 2017-01-31 01:45:12
those are supposed to give different answers (showing that the ordering matters)