ski 2017-02-22 04:45:23
no really, except for the obvious
ski 2017-02-22 04:45:29
s/no/not/
geekosaur 2017-02-22 04:45:31
I didn't find your repo, I used your paste. webRegenerate is lines 53 and 81 and line 32 makes it clear that webRegenerate receives a callback (IO action)
max3 2017-02-22 04:45:49
so liftIO is basically magic
max3 2017-02-22 04:45:51
got it
jstolarek 2017-02-22 04:46:15
ski: what's "obvious"?
geekosaur 2017-02-22 04:46:30
not really magic. it (a) does typechecking to ensure the bottom of a monad stack is IO, and (b) knows how to forward IO callbacks to that IO
ski 2017-02-22 04:46:41
jstolarek : first run the action in the normal fashion, then check the result (with a guard, if you prefer)
max3 2017-02-22 04:46:50
geekosaur, yes i was kidding a little
Tuplanolla 2017-02-22 04:46:57
@hoogle whenM
lambdabot 2017-02-22 04:47:00
Shelly whenM :: Monad m => m Bool -> m () -> m ()
lambdabot 2017-02-22 04:47:01
Shelly.Lifted whenM :: Monad m => m Bool -> m () -> m ()
lambdabot 2017-02-22 04:47:01
Shelly.Pipe whenM :: Monad m => m Bool -> m () -> m ()
jstolarek 2017-02-22 04:47:09
ski: I'm not even able to do that
Tuplanolla 2017-02-22 04:47:11
Is that what you want, jstolarek?
max3 2017-02-22 04:47:25
but that's actually a good explanation - that it sends a computation to the bottom of a stack of computations
jstolarek 2017-02-22 04:47:27
Tuplanolla: no, not exactly
max3 2017-02-22 04:47:30
thank you
jstolarek 2017-02-22 04:47:38
I want this as a guard on a function case
jstolarek 2017-02-22 04:47:48
foo a | p a = ....
ski 2017-02-22 04:47:55
max3 : rather it "lifts" the computation from the bottom of the stack (being I/O), up to the "current layer"
jstolarek 2017-02-22 04:48:00
where p returns Bool in a monad
Tuplanolla 2017-02-22 04:48:00
That's not happening, jstolarek.
geekosaur 2017-02-22 04:48:01
most of which is done by: instance (MonadTrans t, MonadIO m) = MonadIO (t m) where liftIO = lift . liftIO
geekosaur 2017-02-22 04:48:19
(and at the bootom: instance MonadIO IO where liftIO = id)
ski 2017-02-22 04:48:24
jstolarek : `foo a = do b <- p a; bar b where bar True = ...; ...'
ski 2017-02-22 04:48:36
jstolarek : depending, Tuplanolla suggestion may help
Tuplanolla 2017-02-22 04:49:19
Does the `ViewPatterns` thing allow binding inside patterns?
nitrix 2017-02-22 04:49:36
s/ski/bckw/
max3 2017-02-22 04:49:44
ski, that confuses me
max3 2017-02-22 04:50:09
how am i lifting a computation from somewhere to the call site of liftIO?
Tuplanolla 2017-02-22 04:50:14
If so, that could be an option, jstolarek.
ski 2017-02-22 04:51:17
max3 : the layers on top of `IO' add extra "features" (effects) to the base I/O ones. `liftIO' knows how to take an I/O computation, and convert it into a computation whose type *allows* all these extra bells and whistles .. but which in this case actually doesn't make any nontrivial use of them. the "lifted" action *just* does the I/O that the input action does, it does nothing more
ski 2017-02-22 04:51:39
Tuplanolla : what do you mean by "allow bindings" here ?
Tuplanolla 2017-02-22 04:52:08
I was thinking of extending a do block inside a pattern, ski. It's probably not a thing, but you never know.
GuruGuru 2017-02-22 04:52:10
kgadek, byorgey Well the penny has dropped finally :d Thanks!
ski 2017-02-22 04:52:12
max3 : does that make any sense ?
max3 2017-02-22 04:52:23
ski, so it's like lifting computational ability
max3 2017-02-22 04:52:25
in some sense
ski 2017-02-22 04:52:34
Tuplanolla : well, not unless you use `runX' in the pattern ..
kgadek 2017-02-22 04:52:35
GuruGuru: great to hear that :)
jstolarek 2017-02-22 04:53:51
this is frustrating
ski 2017-02-22 04:53:55
max3 : yes, go from a more restricted universe to one where more exotic things can happen. but in this case, not actually make any use of the extra power. you can compare it with `fromIntegral' which can be used to convert an `Integer' to a `Rational' (which always in this case happens to be a rational with denominator `1')
geekosaur 2017-02-22 04:54:12
max3, anyway, the point here is that you could use liftIO to do the operation now, but it is possible webRegenerate does some *other* IO action first that makes the config you need available. so you want to attach it to the callback passed to webRegenerate, so it happens at the right time
jstolarek 2017-02-22 04:55:06
I'm rewriting my code to use state monad so that it's shorter and easier to follow but this limitation of guards would force me to construct a workaround that would be even uglier than the original code, thus defeating the purpose of the whole refactoring
Lokathor 2017-02-22 04:55:52
jstolarek, try using stuff from Control.Monad ?
ski 2017-02-22 04:55:56
jstolarek : `when' or `whenM' doesn't fit your case ?
max3 2017-02-22 04:55:59
geekosaur, https://github.com/databrary/databrary/blob/master/Databrary/Web/Generate.hs#L46
max3 2017-02-22 04:56:07
the answer is no? it just runs the action itself
max3 2017-02-22 04:56:09
right?
Lokathor 2017-02-22 04:56:13
foo a | p a == bar = that's basically "when", right?
ski 2017-02-22 04:56:28
Lokathor : or `if' ..
Lokathor 2017-02-22 04:57:18
right, depending on the output expression and such it might be reducable to "if"
max3 2017-02-22 04:57:25
any thanks for the help. i worry i'm going to exhaust people's patience before i'm competent enough
jstolarek 2017-02-22 04:57:42
ski, Lokathor: no, that won't work. The thing is I have my function written as a series of cases and I want to enter a case depending on the current monadic state
ski 2017-02-22 04:58:07
max3 : generally we try to be patient enough so that you shouldn't have to worry about that
jstolarek 2017-02-22 04:58:18
the only thing that seems like an option is to rewrite my function to consiste of just one case and then use pattern matching
jstolarek 2017-02-22 04:58:38
s/patern matching/case/
jstolarek 2017-02-22 04:59:17
ski: https://github.com/jstolarek/slicer/blob/references/lib/Language/Slicer/Slice.hs#L27
jstolarek 2017-02-22 04:59:23
this is before a rewrite
jstolarek 2017-02-22 04:59:37
store parameter goes into a state monad
geekosaur 2017-02-22 04:59:38
max3, do you know that will always be true? or, more to the point: do you understand *why* the other function is written the way it is? (note: *I* do not know. I have only that working function as a reference; I must assume it defers the IO for a reason)
max3 2017-02-22 05:00:36
geekosaur, do you mean do i know that going forward that function won't change?
geekosaur 2017-02-22 05:00:47
that's another way to put it, yes.
max3 2017-02-22 05:00:57
it won't change unless i change it
max3 2017-02-22 05:01:12
but i do not know why it was written the way it was
geekosaur 2017-02-22 05:01:24
my real point is: if working examples all defer the IO the way line 32 does, then there is likely a good reason for it
geekosaur 2017-02-22 05:01:54
and "cheating" by using liftIO may get you in trouble in the future, if so
max3 2017-02-22 05:02:27
oh i wrote line 32 like that
max3 2017-02-22 05:02:45
that entire do was just passed webRegenerate
max3 2017-02-22 05:02:56
but that's still deferred right?
max3 2017-02-22 05:03:02
doesn't matter if i bind it in a let?
geekosaur 2017-02-22 05:03:37
right, the point is exactly that that one is deferring it, the other one wants to do it directly. if you know that this is just a stylistic difference, go ahead and use liftIO
max3 2017-02-22 05:04:13
the other one is my attempt at refactoring. that <- wasn't there before
max3 2017-02-22 05:04:36
https://github.com/databrary/databrary/blob/master/Databrary/Web/Coffee.hs
max3 2017-02-22 05:04:42
it wasn't io before
max3 2017-02-22 05:04:46
line 21
max3 2017-02-22 05:05:10
binDir comes from Paths_databrary
max3 2017-02-22 05:05:18
anyway you don't need to work too hard on this
max3 2017-02-22 05:05:23
i'm comfortable with this
geekosaur 2017-02-22 05:09:06
allso if you know you don't need to defer the earlier one, consider using liftIO there as well --- because other people looking at the code (this has an annoying tendency to become "you, 6 months later" >.> ) will make the same assumption I did
max3 2017-02-22 05:09:28
that's a good point
max3 2017-02-22 05:09:31
i will do that
ski 2017-02-22 05:09:54
jstolarek : the guards that depend on the store doesn't seem to affect that many subsequent cases, so i'd probably just group such together into a single clause, using `if', or perhaps `when' in some cases
jstolarek 2017-02-22 05:10:43
ski: the problem is that order of these equations matters
jstolarek 2017-02-22 05:10:55
I cannot reorder them arbitrarily
ski 2017-02-22 05:11:05
yes, but it doesn't involve that many equations, from what i can see
jstolarek 2017-02-22 05:11:17
ski: yes, the problem is only with two equations
ski 2017-02-22 05:11:41
jstolarek : no, it's also the `TAssign (Just l) _ _' case
jstolarek 2017-02-22 05:12:08
ah, right
ski 2017-02-22 05:12:21
but that said, not so many equations are involved
ski 2017-02-22 05:13:14
(btw, this is a downside to using guards, when the different conditions aren't mutually exclusive .. the same kind of problem exists in Prolog, with the cut, though the problem is even more pronounced there)
jstolarek 2017-02-22 05:13:34
ski: I don't see how
jstolarek 2017-02-22 05:14:01
given that the first equation must remain first so that it;s not overlapped by the third one
ski 2017-02-22 05:14:13
you have a defining equation with a guard that depends on the store : so identify all later defining equations which could possibly match in case the guard fails
ski 2017-02-22 05:14:30
group these together into a single defining equation, using `if' (at least to begin with)
ski 2017-02-22 05:15:33
hm, yes, i suppose `bwdSlice store (VException VHole) trace' also overlaps with `bwdSlice store v (TVar x)'
jstolarek 2017-02-22 05:15:54
ski: it overlaps most of remaining equations
jstolarek 2017-02-22 05:16:07
because they pattern-match on the last argument
ski 2017-02-22 05:16:55
hm, ok. so try split it up into two subsequent matches ?
ski 2017-02-22 05:18:07
.. in any case, i think all these overlapping patterns are making it hard to grasp
ski 2017-02-22 05:18:37
(perhaps it's hard to avoid using overlapping patterns in your case, i don't know)
ski 2017-02-22 05:20:41
"ExnTy is equal to every type" :/
ski 2017-02-22 05:21:51
(is `deriving instance Ord Type' really needed ?)
jstolarek 2017-02-22 05:22:23
ski: I agree, this is not easy to grasp - but sadly that's how it works
ski 2017-02-22 05:23:32
`isRefTy',&c.,`fstTy',&c. also makes me :/
jstolarek 2017-02-22 05:23:52
ski: yes, same here
merijn 2017-02-22 05:23:55
Is there a Haskell package for computing binary decision trees?
jstolarek 2017-02-22 05:24:04
that whole ExnTy thing is because we don't have a proper type inference
jstolarek 2017-02-22 05:24:23
reported as issue #25
jstolarek 2017-02-22 05:24:56
ski: this really should be rewritten but not before the ICFP deadline :-)
jstolarek 2017-02-22 05:25:10
oh, and good catch with that Ord Type instance
ski 2017-02-22 05:27:16
why `Fun (Code Exp)' rather than something involving `a' ?
jstolarek 2017-02-22 05:29:12
beacuse we never use anything else nad this is to express that invariant
jstolarek 2017-02-22 05:29:19
s/nad/and/
ski 2017-02-22 05:31:36
mhm
ski 2017-02-22 05:33:20
re `TRaise Trace', what if an exception is raised inside the expression computing the exception to raise ?
Tuplanolla 2017-02-22 05:33:20
Is it usually a better idea to explicitly order your monad stack and give it a new type rather than name the mtl constraints (with `ConstraintKinds`) and carry them around?
jstolarek 2017-02-22 05:33:20
you mean a nested exception?
jstolarek 2017-02-22 05:33:20
the most nested exception counts
jstolarek 2017-02-22 05:33:20
ski: https://github.com/jstolarek/slicer/blob/references/examples/exceptions.tml
ski 2017-02-22 05:33:20
i mean the expression computing the exception value to raise doesn't terminate, and so the raising doesn't happen (because the expression raised an exception)
ski 2017-02-22 05:33:20
shouldn't this case be distinguished in the trace from the expression successfully computing an exception value, which is then raised ?
jstolarek 2017-02-22 05:33:52
ski: it should, but we're stilldiscussing what is the best way of doing this
Tuplanolla 2017-02-22 05:34:03
My options are `type MonadServer m = (MonadReader Server m, MonadResource m, MonadState Server m)` and `newtype ServerMonad m a = ServerMonad {runServerMonad :: StateT Server (ReaderT Server (ResourceT m)) a}`.
jstolarek 2017-02-22 05:34:25
sorry, let me put it differently
jstolarek 2017-02-22 05:34:53
I understand that you're asking about something like this: raise (raise "foo") ?
ski 2017-02-22 05:35:04
yes
barrucadu 2017-02-22 05:35:05
Why do you have a Reader Server inside a State Reader?
barrucadu 2017-02-22 05:35:15
That Reader will not see changes made to the State, is that what you want?
jstolarek 2017-02-22 05:35:56
right. So here we construct a TRaise inside a TRaise
jstolarek 2017-02-22 05:36:03
because this is what actually happened
ski 2017-02-22 05:36:07
just like you have a case `TIfExn Trace' for when the condition raises an exception, it would seem to be consistent to have a case `TRaiseExn Trace' when the expression inside a `raise' raises an exception
Tuplanolla 2017-02-22 05:36:19
I think it doesn't matter, barrucadu.
jstolarek 2017-02-22 05:36:36
ski: hm... I'll test that
Tuplanolla 2017-02-22 05:36:45
The reader only applies to constant data used by other threads.
Tuplanolla 2017-02-22 05:36:56
I guess I could swap them around if it looks suspicious though.
ski 2017-02-22 05:37:44
jstolarek : i mean, i don't get the whole framework here (e.g. should there be a type difference between traces that ends with an exception and those that don't ?) -- but from what little i understand, i'd expect consistency here, unless there's a good reason to deviate
jstolarek 2017-02-22 05:38:37
ski: I;m not sure if I have a good answer
jstolarek 2017-02-22 05:38:57
there's no consistency in recording exceptions
jstolarek 2017-02-22 05:39:32
as you noticed there is an TIfExn to record the fact that exception was raised in a condition
jstolarek 2017-02-22 05:39:56
but there are no similar constructs, eg. for operators that take an arbitrary list of arguments
jstolarek 2017-02-22 05:40:09
ski: like most of Haskell projects - get a paper published ;-)
jstolarek 2017-02-22 05:40:15
but seriously
jstolarek 2017-02-22 05:40:22
it's about slicing
ski 2017-02-22 05:40:32
as in type error slicing ?
jstolarek 2017-02-22 05:40:43
or, to be more precise, slicing a functional language with references and exceptions
jstolarek 2017-02-22 05:41:01
I'm not sure what's type error slicing, so probably not
ski 2017-02-22 05:41:22
type error slicing is about giving better diagnoses for type errors
jstolarek 2017-02-22 05:41:35
this is close then
ChaoticSun 2017-02-22 05:41:50
Quit
jstolarek 2017-02-22 05:42:00
this is about giving better diagnoses of results of computations
ski 2017-02-22 05:42:09
basically, instead of flagging the location where an inconsistency was found, we flag all and exactly those locations which (from the POV of the knowledge of the language processor) contribute to the inconsistency
jstolarek 2017-02-22 05:42:15
by figuring out which parts of the code were used to compute a particular component of the result
ertes 2017-02-22 05:42:22
is it possible to have closed associated type synonyms?
ski 2017-02-22 05:42:22
at least one of these must be changed in order to make the inconsistency go away
ski 2017-02-22 05:44:11
"Skalpel: A Type Error Slicer for SML"
ski 2017-02-22 05:44:35
jstolarek : hmm .. sounds related to declarative debuggers
ertes 2017-02-22 05:44:50
nevermind, the question didn't really make sense