quchen 2017-01-30 05:45:29
ph88: You can always use a prettyprinter to implement a serialization library. I don't know your use case, so I don't know whether you should serialize or prettyprint.
quchen 2017-01-30 05:46:01
ph88: In my STGi, I have a prettyprinter that outputs valid STGi programs, which fulfills both the role of a serialization library and a nice-to-humans prettyprinter.
quchen 2017-01-30 05:46:14
ph88: It's much less performant than a pure serializer of course.
nitrix 2017-01-30 05:46:21
nogid: I can't blame you for the question though. It's a very valid question, and a thought one to answer as the nuance of its answer will just fly right above your head if you haven't been exposed to Haskell in any serious manner.
Cale 2017-01-30 05:46:25
I think a lot of what makes Haskell so great is also lost if you never use it in a team of people -- the ability of types to document what people's intentions are in a way that is machine-checked is remarkably useful on a moment-to-moment basis.
nitrix 2017-01-30 05:46:29
nogid: It's a relatively common question too.
lyxia 2017-01-30 05:46:39
ph88: basically you're collecting strings in your structure and concatenating them?
shapr 2017-01-30 05:46:45
nogid: Are you writing up your investigation results somewhere? I'm interested in what/why you're looking into this.
Vq 2017-01-30 05:47:07
shapr: Interesting project, I've never really understood how to best model historical data in a RDBMS
lyxia 2017-01-30 05:47:20
ph88: hmm, you're doing something different for lists.
ph88 2017-01-30 05:48:18
lyxia, yes i'm collection the strings and just print them, and "get rid of the structure"
nogid 2017-01-30 05:48:38
shapr: Not at this time. I'm just trying to get a better understanding.
Cale 2017-01-30 05:49:28
nogid: Types *say* a whole lot more in Haskell than in C++, partly as a knock-on effect of having the default of purity -- we have various types which express that computations can only have certain kinds of effects as well, and the types of pure functions, and especially polymorphic ones, can tell you a lot about what they must be doing.
ph88 2017-01-30 05:49:52
lyxia, eh i meant data Foo = F (String, String) ---> putStrLn $ String ++ String all structure need to be printed eventually. And with lists also in the order from left to right just as tuple or data-fields .. everything from left to right
quchen 2017-01-30 05:50:14
nogid: Well, this is #haskell, full of people that like Haskell. All the stories we could tell you about how we like it have been told countless times; none of them can show you what it is really like, much like reading about French does not teach you what it feels like to speak it. Some people like to learn and speak French once they try it out.
lyxia 2017-01-30 05:50:55
ph88: I mean, for lists you use putStrLn, which prints each element on one line, whereas for fixed length tuples you just concatenated them.
quchen 2017-01-30 05:51:09
nogid: We can tell you as a community of people that wrote a lot of C and C++ and Perl and ASM and what not that we did not regret learing Haskell. :-)
nogid 2017-01-30 05:51:13
quchen: Funny, I can speak French and I don't like it.
lyxia 2017-01-30 05:51:14
ph88: but overall this looks like something you can do with generics.
quchen 2017-01-30 05:51:55
nogid: You might not like Haskell either! That's the point of the example, I guess.
ph88 2017-01-30 05:52:08
lyxia, yeah exactly i was just hoping there is a library that already provide some of this and i would just have to write the function to print my Strings (which are contained in another datatype)
ph88 2017-01-30 05:52:29
lyxia, yeah ok putStrLn was a mistake .. just putStr :P
quchen 2017-01-30 05:52:39
nogid: On the other hand, you might also learn a completely different view on things and like it. There are many other nice views to learn that would be worth your time.
ph88 2017-01-30 05:52:46
lyxia, the strings themselves will contain the newlines so i don't need to add them
ph88 2017-01-30 05:53:00
lyxia, you think i'm best of creating the generics printer myself ?
Cale 2017-01-30 05:53:01
nogid: Here's another anecdote -- the other week, one other member of my team and I pair programmed for 3-4 days and finished converting the web application our team of 7-ish programmers has been working on for over a year such that it is multi-tenant. This is the sort of thing which normally could easily take several weeks if you were working in a more traditional setting.
lyxia 2017-01-30 05:53:07
ph88: yes
ph88 2017-01-30 05:53:20
okay !
ph88 2017-01-30 05:53:31
challenge accepted :P
nogid 2017-01-30 05:53:49
quchen: My main gripe with Haskell so far is that it does add a lot of complexity to achieve its well-intended goals. And while many things may get easier, others get a lot more tedious.
Cale 2017-01-30 05:53:53
nogid: The ability of the compiler to tell us exactly what needed to change in response to some initial changes to how the database was being accessed was just insane in terms of how much it improved our productivity.
nogid 2017-01-30 05:53:59
quchen: one example I can think of is the sieve of eratosthenes
lyxia 2017-01-30 05:54:05
ph88: I can't see what general purpose functionality you can find in a library that would be useful to you here.
Cale 2017-01-30 05:54:35
(Well, the database access stuff changed a bit, and then the authentication tokens also got a new type parameter)
Cale 2017-01-30 05:54:44
nogid: hm?
quchen 2017-01-30 05:55:16
nogid: I know complex code in Haskell, but no particularly complex principles in the language itself
Cale 2017-01-30 05:55:17
nogid: Are you talking about the one which isn't really the sieve of eratosthenes?
Cale 2017-01-30 05:55:25
But looks kind of like it?
quchen 2017-01-30 05:55:38
The one on haskell.org? ಠ_ಠ
ph88 2017-01-30 05:55:41
lyxia, i thought maybe there was a generics framework where you can just implement an instance for your type or something like that. Now i'm worried i will have to implement generics for lists, 1-tuple, 2-tuple, 3-tuple and so on
nogid 2017-01-30 05:55:53
Cale: yeah, and the lengths to which you have to go to get an actual sieve of eratosthenes (via the ST monat)
Cale 2017-01-30 05:55:57
https://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
nogid 2017-01-30 05:55:59
monad*
Cale 2017-01-30 05:56:06
^^ There are some easy real sieves there
Cale 2017-01-30 05:56:09
which don't use ST
lyxia 2017-01-30 05:56:16
ph88: What?
Cale 2017-01-30 05:56:31
If you have a priority queue datastructure handy, it's not hard to do a good job
lyxia 2017-01-30 05:56:40
ph88: You can derive Generic
exio4 2017-01-30 05:57:05
using []'s Monad instance is one of the many things I feel "missing" on other languages
nitrix 2017-01-30 05:57:30
nogid: One could argue that the complexity added are merely different, very powerful, re-usable abstractions.
Cale 2017-01-30 05:57:35
nogid: It's not a one-liner anymore, but it's still not particularly difficult.
exio4 2017-01-30 05:57:48
[unrelated to Haskell] but what is an idiomatic way to do stuff like that in a non-FP lang?
Cale 2017-01-30 05:58:13
exio4: Usually using recursion to do a depth-first search of some kind
nitrix 2017-01-30 05:58:37
nogid: You can kind of think of it like design patterns, except it's not trying to patch recurring issues with the language, but to give you the tools to reason about the problem space.
dfeuer 2017-01-30 05:58:37
The sieve of Eratosthenes is very difficult to implement well in any language.
Cale 2017-01-30 05:58:40
exio4: i.e. you would regard the collection of recursive calls made by a procedure as the "list"
exio4 2017-01-30 05:58:49
Cale: that sounds complicated compared to simply doing xs <- [a,b] :p
Cale 2017-01-30 05:58:56
exio4: yes, it sucks
ph88 2017-01-30 05:59:20
lyxia, for example at the moment i'm using genericShrink and i derive Generic for that. But for pretty printing i would still have to implement the "genericPrint" equivalent function for that, and i don't know what this involves, i thought it might be very complicated
Cale 2017-01-30 05:59:43
dfeuer: This is also a good point
nitrix 2017-01-30 06:00:00
nogid: Most of these abstractions have a very minimal essence. Sometimes you can spend months learning what one of these are and once you have the eureka moment, you'll laugh at yourself for making such a big deal out of it.
nogid 2017-01-30 06:01:09
Cale: But the version with the priority queue is still way more complicated than the imperative version and has higher time complexity by a factor of O(log n) according to the paper
nitrix 2017-01-30 06:01:17
nogid: The thing is, it's a completely different way than you might be used to, to think and approach problems via abstractions.
Cale 2017-01-30 06:01:20
Than which imperative version?
Cale 2017-01-30 06:01:32
Are you sure that imperative version does the same thing?
Cale 2017-01-30 06:01:43
Does the imperative program emit an infinite sequence of primes?
nogid 2017-01-30 06:02:40
Cale: wait, that sieve from the paper doesn't emit an infinite sequence of primes either
Cale 2017-01-30 06:02:46
Yes it does.
nogid 2017-01-30 06:02:49
Cale: it takes a sequence and filters out the non-primes by sieving
buglebudabey 2017-01-30 06:02:52
i'm learning about qubit gates, and the CNOT gate is essentially |A,B> -> |A, B `xor` A>, is this analogous to a state monad almost? or something else maybe?
Cale 2017-01-30 06:02:58
Read it again :)
Cale 2017-01-30 06:03:09
sieve works on an infinite list
lyxia 2017-01-30 06:03:40
ph88: the GHC.Generics documentation describes a simple example http://hackage.haskell.org/package/base-4.9.1.0/docs/GHC-Generics.html
Cale 2017-01-30 06:03:52
The "primes" defined at the bottom of page 8 for example is infinite
nogid 2017-01-30 06:04:19
Cale: oh the xs can be an infinite list
Cale 2017-01-30 06:04:25
yes :)
Cale 2017-01-30 06:04:34
That's mainly what makes it tricky
ph88 2017-01-30 06:04:42
lyxia, i looked at it before, since then i have become fearful :P but i will give it another go
nogid 2017-01-30 06:05:13
Cale: well, it's not the true sieve of eratosthenes algorithm then? As that one takes a fixed-size list and goes through crossing off all the multiples
nitrix 2017-01-30 06:05:14
nogid: Just functors for example. You can find an immediate practical use as containers, then you find out their level of abstraction reaches beyond containers to contexts, then you find out there's even more powerful, as abstractions of abstractions (once you get to category theory with categories of categories).
nitrix 2017-01-30 06:05:28
nogid: And it's the same concept from the begining, it just goes a very, very long way.
Cale 2017-01-30 06:05:40
nogid: Well, it's the same, it's just the size is being fixed at infinity ;)
Cale 2017-01-30 06:06:07
nogid: and the tricky bit is interleaving which multiple you're currently crossing off for
Cale 2017-01-30 06:06:18
so that you can go through in one pass
nogid 2017-01-30 06:06:25
Cale: the imperative algorithm would run forever on an infinite list trying to cross off all the multiples of 2 :)
Cale 2017-01-30 06:06:29
(because two obviously wouldn't do)
Cale 2017-01-30 06:06:33
right
lyxia 2017-01-30 06:06:38
ph88: the example is pretty close to your use case. instead of converting values to [Bool] you want to get a String.
ph88 2017-01-30 06:07:45
:)
roxxik 2017-01-30 06:08:00
buglebudabey: i can't see the similarity with state
buglebudabey 2017-01-30 06:09:30
roxxik, i guess i'm thinking it's some kind of monad because they can be composed like |A B> >>= (\|a b> -> return (A `xor` B))
buglebudabey 2017-01-30 06:10:05
return (a `xor` b) **
nogid 2017-01-30 06:10:06
Cale: In the simple map version, I don't get why x*x is inserted as opposed to x+x
nogid 2017-01-30 06:10:54
Cale: oh is that because it works for 2 and the factor of 2 will be found either way, hmm.. seems a bit unintuitive though
roxxik 2017-01-30 06:12:15
buglebudabey: then it would be monadic, State is often represented by s -> (a,s), or even better with arrow style by (b,s) -> (a,s) or kleisli style: b -> s -> (a,s) those are all pretty much interchangeable
nogid 2017-01-30 06:12:23
Cale: reconsidering it, I see how that's more efficient, but it still looks like it catches the special case of 4=2*2 by sheer luck
buglebudabey 2017-01-30 06:12:45
roxxik, if you replace |A B> with (A,B) is it still different from State then?
nogid 2017-01-30 06:12:57
Cale: certainly takes some trying it out to see that the algorithm is correct
buglebudabey 2017-01-30 06:12:57
i guess it is
roxxik 2017-01-30 06:14:17
hmmm you mean something along the lines of cnot b = do { a <- get; return (a `xor` b) } or if run through some State evaluator :: cnot a b = (a, a `xor` b)
roxxik 2017-01-30 06:15:02
im not sure how you represent qubits in haskell...
buglebudabey 2017-01-30 06:15:20
roxxik, i'm trying to figure that out myself right now
NickHu 2017-01-30 06:16:06
roxxik 2017-01-30 06:16:50
most circuit stuff can be looked at like arrows... maybe cnot would be of type `q (a,b) (a,???)` where ??? depends on the type of a `xor` b
nogid 2017-01-30 06:18:18
Cale: this quote from the paper is what worries me a bit about Haskell: "But, despite fooling some of us for years, the algorithm we began with isn't the real sieve, nor is it even the most efficient one liner that we can write."
nogid 2017-01-30 06:18:37
Cale: in the context of game development where performance is crucial
buglebudabey 2017-01-30 06:18:53
roxxik, i think it would always be :: Qubit -> Qubit -> Qubit
roxxik 2017-01-30 06:19:15
but isn't cnot taking in two qubits?
buglebudabey 2017-01-30 06:19:34
roxxik, yeah, my type takes in two quibits and outputs 1
roxxik 2017-01-30 06:19:51
hmmm
bitemyapp 2017-01-30 06:19:53
nogid: do you often write your own prime sieves in game development
bitemyapp 2017-01-30 06:20:57
nogid: you're focusing on the wrong things anyway. What'll bite you using GHC RTS for game dev is GC (this'll start to really hurt as heap gets >1gb) and the fact that you'll be fixing up bindings and libraries as you go in order to get things done.
bitemyapp 2017-01-30 06:21:25
you can use GHC Haskell to make indie-grade games just fine. That's all most people asking whether they should use a programming language for gamedev or not are likely to do anyway.
bitemyapp 2017-01-30 06:21:45
but if the point is learning game dev, Haskell will mostly add work to that unless you're specifically interested in FP + Game dev.
nogid 2017-01-30 06:22:03
bitemyapp: I often write performance-critical mutable data structures, like dynamic delaunay triangulations for collision detection navmeshes
nogid 2017-01-30 06:22:18
not sure how I would even approach that in Haskell
dfeuer 2017-01-30 06:24:01
nogid: we have mutable unboxed vectors and arrays, so you can make stuff happen if you like.
bitemyapp 2017-01-30 06:24:44
nogid: so, like I said, your main impassable problem is going to be GC
bitemyapp 2017-01-30 06:25:05
nogid: I know when/why people need mutable data structures, that's not a problem nor is it the main problem using GHC Haskell for game dev
bitemyapp 2017-01-30 06:25:23
nogid: you're spinning your wheels. If the point is game dev for its own sake, use standard tooling and languages.
dfeuer 2017-01-30 06:25:26
GHC is adding this "compact region" feature to alleviate the GHC issues.
bitemyapp 2017-01-30 06:25:37
nogid: if you specifically want to learn how to do game dev in Haskell, then do it in Haskell.
nogid 2017-01-30 06:25:45
bitemyapp: yeah, that's true. There's no way to disable GC with Haskell I assume?
nogid 2017-01-30 06:26:03
bitemyapp: I know D has GC by default, but it can be turned off.
Rembane 2017-01-30 06:26:27
nogid: You can give the runtime parameters such that the GC is hardly ever run.
bitemyapp 2017-01-30 06:26:27
not usefully, no, you cannot shut the GC off.
bitemyapp 2017-01-30 06:26:36
There is no quick fix for this.
buglebudabey 2017-01-30 06:27:30
roxxik, how is this: http://lpaste.net/351797, although idk how to incorporate the Qubit datatype
Tuplanolla 2017-01-30 06:27:34
How well would pushing the unpleasant parts to a foreign land work?
bitemyapp 2017-01-30 06:28:18
Tuplanolla: fine, but you still have semi-non-deterministic pauses and keeping GHC's heap tiny is hard even if you're tossing stuff over the fence.
bitemyapp 2017-01-30 06:28:45
Cowley had a trick for this with his robotics work where he'd invoke a GC pass when there was some breathing time
bitemyapp 2017-01-30 06:29:03
that's not as easy in games where you have at most 16ms and need most of that for the actual game
roxxik 2017-01-30 06:29:42
buglebudabey: it looks unfortunate, that an operation needs to be represented as a data type
roxxik 2017-01-30 06:29:56
buglebudabey: doesn't feel haskelly
bitemyapp 2017-01-30 06:30:01
It's just not a good use of time unless you specifically want to see how far you can take a game in Haskell, but you'll spend so much time just making the game engine, yeesh. farthest anyone got were the FRP folks that made a Quake 3 clone engine thingy.
nogid 2017-01-30 06:30:35
Yeah, it's probably best to write functional style in C++ directly for gamedev
buglebudabey 2017-01-30 06:30:57
roxxik, i see what you mean, what if the monad i want is essentially a control gate, where theres a bit that always determine whether the output changes? i'm just trying to find a way to generalize thiss
bitemyapp 2017-01-30 06:31:15
The Rust people have some pretty cool stuff coming down the pipe, but for now, the best choices are C++ or something like Unity.
nogid 2017-01-30 06:31:19
the Quake 3 engine is very interesting though, the way they represent the navigation space as a BSP tree
nogid 2017-01-30 06:31:55
unfortunately newer engines/games all seem to have converged toward a triangle soup representation with brute-force checking inside a uniform grid
roxxik 2017-01-30 06:31:56
buglebudabey: what do you want to do with those qubits?
nogid 2017-01-30 06:32:32
bitemyapp: I looked at Rust already but the lifetime annotations are painful and sometimes disallow things that would actually be perfectly safe
buglebudabey 2017-01-30 06:32:40
well, the user would define the k in ____ >>= k, and k would be the controll gate, in this case the cnot
nogid 2017-01-30 06:32:45
bitemyapp: maybe things have changed by now, I should look into it again
bitemyapp 2017-01-30 06:32:54
nogid: if that's too hard for you, gamedev is going to drive you fucking crazy.
buglebudabey 2017-01-30 06:32:59
roxxik, see above
bitemyapp 2017-01-30 06:33:32
statically enforced lifetimes are way easier than learning/doing gamedev, or for that matter, cleaning up mistakes made with lifetimes at runtime.
nogid 2017-01-30 06:33:34
bitemyapp: not too hard, just too much of a price to pay to fix something that isn't actually a problem for me (lifetime and memory managemend issues)
bitemyapp 2017-01-30 06:33:40
uh huh.
bitemyapp 2017-01-30 06:33:45
well, I'm out. Good luck!
Tuplanolla 2017-01-30 06:33:50
Game development would drive you crazy anyway.
nogid 2017-01-30 06:35:18
It's not that lifetime annotations are hard. It's just that I already have them in C++ in the form of unique_ptr, references, or plain value members.
nogid 2017-01-30 06:35:45
and those don't impose arbitrary restrictions
Xeronate 2017-01-30 06:35:48
Why do you need () are k+1 for: dropK k l = (take (k) l) ++ (drop (k+1) l)
cocreature 2017-01-30 06:36:18
Xeronate: function application has higher precedence than +
cocreature 2017-01-30 06:36:34
Xeronate: so drop k + 1 would be parsed as (drop k) + 1
jle` 2017-01-30 06:36:39
Xeronate: without the parentheses, drop k + 1 l is (drop k) + (1 l)
cocreature 2017-01-30 06:36:47
oh yeah I forgot about the l
Xeronate 2017-01-30 06:36:54
ah thanks
glguy 2017-01-30 06:37:02
Xeronate: The only parentheses you need there are: dropK k l = take k l ++ drop (k+1) l
jle` 2017-01-30 06:37:03
but you also don't need the parentheses around k
osa1 2017-01-30 06:37:04
it seems like there's no way to detect that the stream is exhausted in a concurrent pipe once I get a Producer from an Input. am I missing anything?
jle` 2017-01-30 06:37:07
or around take k l
Cale 2017-01-30 06:37:09
Xeronate: The general rule is that function application (whitespace) binds more tightly than any infix operator
Cale 2017-01-30 06:37:28
Xeronate: (and it associates to the left)
osa1 2017-01-30 06:38:26
I was hoping to do things like spawning a concurrent pipe that receives from a Producer, logs it to a DB or file and releasing the resources (e.g. flush the file and close it) when the Producer is exhausted. it seems like I can't do that using concurrent pipes.
cocreature 2017-01-30 06:38:47
osa1: you can't detect termination in plain pipes. what you can do is write a function that takes a producer and does something with it.
cocreature 2017-01-30 06:39:07
osa1: pipes-parse has a "isEndOfInput" parser that you could use
osa1 2017-01-30 06:39:31
cocreature: just to understand pipes better, am I asking for something unreasonable? e.g. maybe I'm doing this wrong
cocreature 2017-01-30 06:41:07
osa1: no that's completely reasonable. if you use pipes you have to pay for the simple and consistent interface by restricting the operations you can conform. if this is not enough you need to write functions that take a Pipe as an input
cocreature 2017-01-30 06:41:42
osa1: pipes-parse deals with a lot of things like detecting termination so you probably want to take a look at this
cocreature 2017-01-30 06:41:49
even if you are not parsing anything
osa1 2017-01-30 06:43:43
I see it's using `next`
osa1 2017-01-30 06:43:56
btw thanks cocreature
cocreature 2017-01-30 06:43:57
yeah "next" is one of these functions that deconstructs a producer