Search Haskell Channel Logs

Sunday, March 5, 2017

#haskell channel featuring tsahyt, glguy, johnw, ph88, maerwald, ertes, and 7 others.

bollu 2017-03-05 07:45:16
ertes: I see, cool
ph88 2017-03-05 07:45:21
glguy, documentation mentions peek at what the structure would be like with an edited result
saurabhnanda 2017-03-05 07:45:24
ertes: interesting. Can you write a type-family such that you "map" a -> b, c -> d, and then (a, c) -> (b, d) happens automagically?
ph88 2017-03-05 07:45:47
peek has no documentation only type signature peek :: s -> w a -> a
saurabhnanda 2017-03-05 07:45:49
what is an injective type family?
ertes 2017-03-05 07:46:03
saurabhnanda: not sure what you mean… a type synonym family is pretty much a type function, but with some restrictions
cocreature 2017-03-05 07:46:18
saurabhnanda: injective means that there are no two inputs which map to the same outputs
ph88 2017-03-05 07:46:21
how can i use holesOf to first search an element in a structure, then view it, modify it, and then put it back ?
glguy 2017-03-05 07:46:26
ph88: if you don't understand the types you can just try out the two argument ordering s
glguy 2017-03-05 07:46:54
ph88, you can 'extract' to see the current value
ertes 2017-03-05 07:46:58
saurabhnanda: injectivity lets the compiler decide the argument from the result… think of fundeps in both directions
saurabhnanda 2017-03-05 07:47:06
ertes: Columns PGInt4 = Int64; Columns PGText = Text; and then this happens automagically ==> Columns (PGInt4, PGText) = (Int64, Text)
ph88 2017-03-05 07:47:39
how can i search when i can only see the current value ?
ph88 2017-03-05 07:47:56
this stuff is totally new to me :|
ertes 2017-03-05 07:48:10
saurabhnanda: type instance Columns (a, b) = (Columns a, Columns b)
johnw 2017-03-05 07:48:10
> [1,2,3,4] & traverse.filtered (==3) .~ 5
glguy 2017-03-05 07:48:11
just play with it a bit in ghci
lambdabot 2017-03-05 07:48:15
[1,2,5,4]
johnw 2017-03-05 07:48:23
> [1,2,3,4] & _last .~ 5
saurabhnanda 2017-03-05 07:48:24
ertes: but do I need to define that manually
lambdabot 2017-03-05 07:48:27
[1,2,3,5]
ertes 2017-03-05 07:48:31
saurabhnanda: yes, of course
saurabhnanda 2017-03-05 07:48:34
ertes: because that would not scale for the problem I have in mind
glguy 2017-03-05 07:48:41
or figure out what it is you don't understand specifically and I'll try to answer
ertes 2017-03-05 07:48:47
saurabhnanda: tuples don't scale in general
saurabhnanda 2017-03-05 07:49:08
ertes: scale != performance scaling.
ertes 2017-03-05 07:49:19
saurabhnanda: but 2-tuples can be nested arbitrarily
bollu 2017-03-05 07:50:19
saurabhnanda: you can define the instances the way ertes showed for n-tuples as well
bollu 2017-03-05 07:50:35
saurabhnanda: though I'm not sure I interpreted your question right
ertes 2017-03-05 07:50:47
Columns ((a, b), (c, d)) = (Columns (a, b), Columns (c, d)) = ((Columns a, Columns b), (Columns c, Columns d))
saurabhnanda 2017-03-05 07:51:12
I"m trying to come up with a solution where I define the mappings between PG types and Haskell types in one place, and then I can combine them in any record or tuple type without having to write boilerplate for that specific record or tuple type.
saurabhnanda 2017-03-05 07:51:43
or the standard answer to that is any other API related to tuples, right?
ertes 2017-03-05 07:51:49
saurabhnanda: i don't know why you need a type *mapping* there, but regardless, generics might solve your problem
saurabhnanda 2017-03-05 07:51:54
write shitloads of them up to 64 tuples?
bollu 2017-03-05 07:52:12
saurabhnanda: why are you getting those many tuples in the first place?
saurabhnanda 2017-03-05 07:52:13
Column (a, b) = (Column a, Column b)
saurabhnanda 2017-03-05 07:52:26
Column (a, b, c) = (Column a, Column b, Column c)
saurabhnanda 2017-03-05 07:52:30
and so on... till 64
saurabhnanda 2017-03-05 07:52:38
bollu: SQL queries
ertes 2017-03-05 07:52:46
saurabhnanda: why do you get those tuples?
bollu 2017-03-05 07:52:50
saurabhnanda: you can use some template haskell
cocreature 2017-03-05 07:52:52
sounds like you want to generate instances using generics
bollu 2017-03-05 07:53:07
cocreature: GHC.Generic?
saurabhnanda 2017-03-05 07:53:10
Full context = I'm trying to simplify Opaleye :)
ertes 2017-03-05 07:53:17
yes, if anything, generics is probably the best answer, but a better answer is not to create those tuples in the first place
bollu 2017-03-05 07:53:37
saurabhnanda: ohh, right, you had asked about profunctor in Opaleye the other day right?
saurabhnanda 2017-03-05 07:53:42
tomjaguarpaw: is around here?
cocreature 2017-03-05 07:53:45
bollu: or generics-sop or one of the other generics libraries
saurabhnanda 2017-03-05 07:53:52
bollu: yep!
cocreature 2017-03-05 07:54:02
but you can't magically make up instances without defining them somehow
saurabhnanda 2017-03-05 07:54:45
so, I guess "scaling" the type-families to tuples is simple. Define them for 64 tuples in the core library and be done with it. Profunctors have also done that. Every single library that deals with tuples does that.
saurabhnanda 2017-03-05 07:54:52
but with record-types it's a different problem.
bollu 2017-03-05 07:54:53
saurabhnanda: tangential question: do you always get the results of SQL queries as tuples? can you not get them as a record type or something
saurabhnanda 2017-03-05 07:55:08
which is where we are stuck with a bit of TH.
saurabhnanda 2017-03-05 07:55:37
bollu: getting them with record types makes the problem even harder, no?
bollu 2017-03-05 07:55:40
saurabhnanda: you can write a function that does (a -> b -> c -> d) to (PGtype a) -> (PGType b) -> (PGType c) -> (PGType d) by using the "printf" trick I think
davean 2017-03-05 07:55:56
bollu: That generally requires template haskell or a wrapper
bollu 2017-03-05 07:56:01
davean: ah
bollu 2017-03-05 07:56:12
davean: I assumed the "printf" style trick + type families could work.
davean 2017-03-05 07:56:27
bollu: the problem is you don't "know" what the query is returning persay
ph88 2017-03-05 07:56:28
glguy, maybe there is a tutorial somewhere to get started? i never worked with lens before
ph88 2017-03-05 07:56:35
i saw a video about get and set though
bollu 2017-03-05 07:56:50
davean: I'm not sure what you mean by that
davean 2017-03-05 07:56:59
bollu: you've got a miss-match problem where you don't have a typed return value from the DB
bollu 2017-03-05 07:57:26
davean: but this is happening inside haskell right? where queries are haskell functions?
davean 2017-03-05 07:57:37
bollu: no, the problem is its external
davean 2017-03-05 07:57:45
so typing the return of a query is just hard
bollu 2017-03-05 07:57:51
davean: ah, OK, I'm missing this bit of context
davean 2017-03-05 07:58:20
you're interacting with a remote API with very little guarrentee about what it'll hand you back
davean 2017-03-05 07:58:33
It tends to be consistent but underdefined
davean 2017-03-05 07:58:53
so, the TH approch is "lets look at the DB, assume it doesn't change, and generate code that matches what we see"
davean 2017-03-05 07:59:02
which of course breaks, rather hard, if something DOES change
bollu 2017-03-05 07:59:11
hm
saurabhnanda 2017-03-05 07:59:31
davean: so the problem is not at that step
saurabhnanda 2017-03-05 07:59:47
davean: we've already assumed what the columns are; and what their types are
davean 2017-03-05 07:59:56
saurabhnanda: ah, I missed that
thoughtpolice 2017-03-05 08:00:21
davean: I have no idea what you mean. Opaleye already assumes the DB matches the schema; that is a completely independent problem. You are already relying on instance selection; the question is whether you can guide instance selection further so that it not only picks the right column results, but further gives you the right Haskell results.
saurabhnanda 2017-03-05 08:00:33
davean: now, after we've done composing all the complicated SQL queries dealing with (Column x) types; we want to convert them to Haskell types easily
davean 2017-03-05 08:00:33
thoughtpolice: I think I missed something
thoughtpolice 2017-03-05 08:00:34
I think. Either way I definitely think there's a way to do this in Opaleye, but I'm not sure what it would look like.
saurabhnanda 2017-03-05 08:00:39
which is where the idea of functional dependency between (columns -> haskells)
thoughtpolice 2017-03-05 08:00:56
davean: Yeah. (Relatedly, I actually _do_ want to combine Opaleye with a TH-level schema check, though...)
saurabhnanda 2017-03-05 08:01:11
thoughtpolice: we're working on that with opaleye-helpers
thoughtpolice 2017-03-05 08:01:39
saurabhnanda: Link?
bollu 2017-03-05 08:01:41
saurabhnanda: so, you also want to convert the "Column x" types to record types?
saurabhnanda 2017-03-05 08:01:44
thoughtpolice: taking a page out of the HRR handbook. Use TH to look at the schema and generate all the Opaleye boilerplate.
benzrf 2017-03-05 08:02:09
so this is closed, but i'm having this exact issue https://ghc.haskell.org/trac/ghc/ticket/12216
saurabhnanda 2017-03-05 08:02:24
thoughtpolice: https://github.com/vacationlabs/opaleye-helpers -- heavy WIP. Developing alongside a production app to make sure it fits real-world requirements.
benzrf 2017-03-05 08:02:47
am i just on an eight-month-old version of ghc...?
saurabhnanda 2017-03-05 08:03:02
but we still hate the fact that everything in Opaleye needs a type signature because of the way it's structured.
thoughtpolice 2017-03-05 08:03:24
benzrf: It was reported in 8.0.1, but there is no indication in the ticket it was merged to the stable branch. It is probably not in 8.0.2, if that's what you're using.
davean 2017-03-05 08:03:26
benzrf: what version are you on?
saurabhnanda 2017-03-05 08:03:29
From https://www.stackage.org/haddock/lts-7.14/opaleye-0.5.2.2/Opaleye-RunQuery.html#v:runQuery -- runQuery's use of the Default typeclass means that the compiler will have trouble inferring types. It is strongly recommended that you provide full type signatures when using runQuery.
benzrf 2017-03-05 08:03:31
oh
benzrf 2017-03-05 08:03:38
oh damn i'm still on 8.0.1... that's very strange
benzrf 2017-03-05 08:03:45
did .2 only come out recently?
davean 2017-03-05 08:04:05
benzrf: Jan
thoughtpolice 2017-03-05 08:04:05
Yes, a few weeks ago.
benzrf 2017-03-05 08:04:08
aha
thoughtpolice 2017-03-05 08:04:09
Or, yes.
benzrf 2017-03-05 08:04:10
oops!
davean 2017-03-05 08:04:15
Jan 11th to be specific
maerwald 2017-03-05 08:04:16
you're so retro :p
ph88 2017-03-05 08:04:37
if holesOf returns a list of the structure, what is the dual function that creates a structure back from the list ?
bollu 2017-03-05 08:04:56
saurabhnanda: where are the record types here?
thoughtpolice 2017-03-05 08:05:07
benzrf: No, it actually looks like it was fixed in the 8.0.x branch. So if you update, you should be OK.
benzrf 2017-03-05 08:05:16
cool!
thoughtpolice 2017-03-05 08:05:21
The ticket just got lost in the ether, I suppose.
saurabhnanda 2017-03-05 08:06:20
thoughtpolice: https://github.com/vacationlabs/opaleye-helpers/pull/1/files#diff-04c6e90faac2675aa89e2176d2eec7d8 -- check the README here
saurabhnanda 2017-03-05 08:06:54
bollu: so the `haskells` type can be a record if you want. But that forces you to define these weird typeclass instances
tsahyt 2017-03-05 08:07:06
after many more hours of trying I'm starting to think that this thing doesn't have a valid ArrowLoop instance
thoughtpolice 2017-03-05 08:07:11
saurabhnanda: Thanks! I'm was hoping someone was already going down this path. (I don't really use or write TH very often)
tsahyt 2017-03-05 08:07:18
I now have two that typecheck
bollu 2017-03-05 08:07:26
saurabhnanda: I see
tsahyt 2017-03-05 08:07:28
but don't seem to ever terminate even for a simple example
tsahyt 2017-03-05 08:07:36
ertes: are you around?
ertes 2017-03-05 08:09:20
tsahyt: pong
tsahyt 2017-03-05 08:10:59
ertes: I've been tearing my hair out over implementing an ArrowLoop instance, and since you've written at least two libraries with arrow interfaces I thought you might know more. I've got a Wave a type which is the same as Word64 -> a. On top of that I have a newtype for Wave a -> Wave b. Since waves are a functor, its image forms a category, the arrows of which I want to model. But I can't figure out how to
tsahyt 2017-03-05 08:11:01
implement loop without it just recursing endlessly
tsahyt 2017-03-05 08:11:38
the reason why I want an arrow interface here is because it's the closest to the dataflow diagrams that are ubiquitous in DSP literature, so I'd just like to try how far that takes me
tsahyt 2017-03-05 08:12:40
I was thinking that since those are just functions, it should be pretty straight-forward to just adopt the ArrowLoop instance from (->) but that turned out not to work either
tsahyt 2017-03-05 08:14:23
so I guess my question is really whether you can give me some pointers as to how this would work, or whether it can work at all
ertes 2017-03-05 08:16:45
tsahyt: paste?
ertes 2017-03-05 08:18:50
tsahyt: BTW, your reasoning as to why you want an arrow interface is misguided
tsahyt 2017-03-05 08:19:15
hmm, lpaste is being slow. hold on
ertes 2017-03-05 08:19:32
the arrow interface is objectively inferiour to the monadic interface… it's not something you'd want, but rather something you can't do without in some cases
ertes 2017-03-05 08:19:50
*inferior
tsahyt 2017-03-05 08:20:12
http://sprunge.us/edZg?hs
tsahyt 2017-03-05 08:20:32
nevermind the second type parameter to Wave in the WaveA definition. I was sloppy removing the irrelevant part
tsahyt 2017-03-05 08:20:50
(Waves are also parameterized over a sample rate parameter)
ertes 2017-03-05 08:21:44
tsahyt: how about (type WaveA r a b = Wave r a -> Wave r b)?
ertes 2017-03-05 08:22:12
and: type Wave = (->)
tsahyt 2017-03-05 08:22:14
I've thought about that, but then I always get the wave as a whole when using <- in arrow notation I think?
tsahyt 2017-03-05 08:22:30
and about the type synonym for wave, I'd really rather not do that. I've got many things depending on the first parameter being words
ertes 2017-03-05 08:22:33
you don't use arrow notation… you use 'let'
ertes 2017-03-05 08:22:45
well
ertes 2017-03-05 08:22:52
type Wave = (->) Word64
tsahyt 2017-03-05 08:23:05
yes, but then I lose the type parameter, which is quite crucial at other points
ertes 2017-03-05 08:23:21
well, then… type Wave = (->)
ertes 2017-03-05 08:23:22
=)
tsahyt 2017-03-05 08:23:29
no I mean the r
ertes 2017-03-05 08:23:33
yes
ertes 2017-03-05 08:23:41
oh, r is really just phantom?
tsahyt 2017-03-05 08:23:56
yes, newtype Wave (r :: Nat) a = ...
tsahyt 2017-03-05 08:24:08
I must make sure not to mix waves of different sample rates
ertes 2017-03-05 08:24:54
i see… at least i'd replace WaveA by simply using (->)
tsahyt 2017-03-05 08:26:10
I've thought about that. It'd at least save me from some worries. but this whole thing also sparked my curiosity as to how a proper ArrowLoop instance for the existing type would look like.
ertes 2017-03-05 08:26:22
you're just forcing yourself to use a much noisier syntax and slower code
tsahyt 2017-03-05 08:26:51
why slower? newtypes should be free, shouldn't they?
ertes 2017-03-05 08:27:17
ArrowLoop for functions is pretty straightforward, and you're basically just writing a version of that with some wrapping/unwrapping
ertes 2017-03-05 08:27:26
newtypes are free, but the arrow interface is not
tsahyt 2017-03-05 08:27:52
right I hadn't thought of that
ertes 2017-03-05 08:28:05
it requires explicit side channels most of the time, which means lots and lots of tuple building and pattern-matching
ertes 2017-03-05 08:28:20
that's why you have stuff like 'first' and (***)
tsahyt 2017-03-05 08:28:24
but all I've been trying to do was to adapt the ArrowLoop (->) instance to WaveA, which never terminated even for simple examples
ertes 2017-03-05 08:29:08
try to write this, if you're curious: loopFunc :: ((a, r) -> (b, r)) -> a -> b
tsahyt 2017-03-05 08:29:24
I have, and that works
tsahyt 2017-03-05 08:32:08
ertes: when specializing loop to Wave a -> Wave b, I get (Wave a, r) -> (Wave b, r) -> Wave a -> Wave b. but for WaveA the type is slightly different. After the newtype unwrapping it's (Wave (b,d) -> Wave (c,d)) -> Wave b -> Wave c
benzrf 2017-03-05 08:32:56
@djinn ((a, r) -> (b, r)) -> a -> b
lambdabot 2017-03-05 08:32:57
-- f cannot be realized.
benzrf 2017-03-05 08:33:00
i didn't think it could!
benzrf 2017-03-05 08:33:04
hmmmmm
tsahyt 2017-03-05 08:33:31
:t \f b -> let (c,d) = f (b,d) in c
johnw 2017-03-05 08:33:31
btw, that's awfully close to what ArrowLoop does
lambdabot 2017-03-05 08:33:33
((t1, t2) -> (t, t2)) -> t1 -> t
johnw 2017-03-05 08:33:51
and tsahyt's defintion is awfully close to the instance for (->) :)
tsahyt 2017-03-05 08:34:01
johnw: iirc it's exactly the same
tsahyt 2017-03-05 08:34:04
up to naming anyhow
benzrf 2017-03-05 08:34:24
oh, cute
johnw 2017-03-05 08:34:42
tsahyt: oh nice, exactly exactly
tsahyt 2017-03-05 08:34:48
johnw: well I've been looking at it a lot today
johnw 2017-03-05 08:34:54
I still want to know what the ArrowLoop instance for free arrows should be
tsahyt 2017-03-05 08:35:09
well I still want to know what the instance should be for my type :/
tsahyt 2017-03-05 08:35:19
but I guess I'll just give up and use the type synonym instead
tsahyt 2017-03-05 08:35:44
it should have just been some unwrapping, but oh well
johnw 2017-03-05 08:35:52
tsahyt: pastie
tsahyt 2017-03-05 08:36:04
http://sprunge.us/edZg?hs
tsahyt 2017-03-05 08:36:24
this is what I ended up with. it ends up producing infinite loops for examples that really should work
tsahyt 2017-03-05 08:36:41
interestingly enough, it does not even bring up CPU usage while it does so
johnw 2017-03-05 08:37:20
what you pasted has some hard errors in it
tsahyt 2017-03-05 08:37:23
johnw: in case you're wondering, there's an additional phantom parameter to Wave, which I forgot to remove in some places
johnw 2017-03-05 08:37:25
newtype WaveA a b = WaveA { process :: Wave r a -> Wave r b } ?
tsahyt 2017-03-05 08:37:31
yes, wait I'll add them back in
johnw 2017-03-05 08:37:43
that's ok, my mayfly attention span just died
tsahyt 2017-03-05 08:38:33
http://sprunge.us/bAhI?hs
ertes 2017-03-05 08:41:56
> let (x, y) = undefined in ()
lambdabot 2017-03-05 08:42:01
()
ertes 2017-03-05 08:42:19
tsahyt: as far as i see your 'loop' implementation is correct
ertes 2017-03-05 08:42:54
tsahyt: the only potential for error i see there is excess strictness, but i can't see any
ertes 2017-03-05 08:44:08
however, semantically speaking it may not exactly do what you think it does: given (loop f), at each point in time the input wave of 'f' is a wave that has as its second component the feedback value *at every point in time*
ertes 2017-03-05 08:44:27
the feedback value of that point in time that is