seangrove has quit [Remote host closed the connection]
seangrove has joined #ocaml
jahuri has joined #ocaml
infinity0_ has joined #ocaml
infinity0_ has quit [Changing host]
infinity0 is now known as Guest60134
infinity0 has joined #ocaml
Haudegen has quit [Read error: Connection reset by peer]
seangrove has quit [Ping timeout: 248 seconds]
seangrove has joined #ocaml
zolk3ri has quit [Remote host closed the connection]
jmiven has quit [Quit: co'o]
jmiven has joined #ocaml
jao has joined #ocaml
ygrek has joined #ocaml
nicoo has quit [Ping timeout: 255 seconds]
shinnya has quit [Ping timeout: 248 seconds]
nicoo has joined #ocaml
mfp has quit [Ping timeout: 276 seconds]
whoman has quit [Ping timeout: 264 seconds]
whoman has joined #ocaml
spew has joined #ocaml
troydm has quit [Ping timeout: 256 seconds]
jonh has joined #ocaml
troydm has joined #ocaml
jao has quit [Ping timeout: 268 seconds]
nomicflux has quit [Quit: nomicflux]
spew has quit [Ping timeout: 248 seconds]
tsani has joined #ocaml
nomicflux has joined #ocaml
<remexre>
I'm having trouble getting `opam switch 4.06.0+musl+static+flambda' to work on Ubuntu Trusty -- it looks like the Ubuntu musl packages don't contain musl-clang, only musl-gcc, whereas 4.06.0+musl+static+flambda is configured to use musl-clang
<remexre>
Is there a known workaround for this? Surprisingly, I haven't actually been able to find anyone with the same issue, googling around.
spew has joined #ocaml
troydm has quit [Ping timeout: 240 seconds]
jimmyrcom has quit [Ping timeout: 264 seconds]
jimmyrcom_ has quit [Ping timeout: 264 seconds]
troydm has joined #ocaml
govg has joined #ocaml
jimmyrcom has joined #ocaml
jimmyrcom_ has joined #ocaml
spew has quit [Ping timeout: 260 seconds]
shinnya has joined #ocaml
sh0t has quit [Remote host closed the connection]
jimmyrcom has quit [Ping timeout: 248 seconds]
jimmyrcom_ has quit [Ping timeout: 248 seconds]
cbot has joined #ocaml
tarptaeya has joined #ocaml
jahuri has quit [Ping timeout: 240 seconds]
nomicflux has quit [Quit: nomicflux]
jimmyrcom_ has joined #ocaml
jimmyrcom has joined #ocaml
nomicflux has joined #ocaml
nomicflux has quit [Client Quit]
pierpa has quit [Quit: Page closed]
<aantron>
dmbaturin: i'm interested in what the outcome of debugging that lwt issue will be
<dmbaturin>
aantron: Let me try to make a self-contained example.
<aantron>
btw sorry i just scrolled up and saw your earlier message
<aantron>
(while looking for an even earlier one by someone else)
<aantron>
it seems i don't get all notifications delivered reliably
<dmbaturin>
I've stepped through it in the debugger, and in the debugger it does work, somehow.
<aantron>
still not seeing anything wrong. are you calling Lwt_main.run somewhere?
<dmbaturin>
This kind of bugs would be more typical for "normal" threads than promises, lol.
<aantron>
:p
<dmbaturin>
No, no Lwt_main.run there.
<aantron>
it's still timing-dependent I/O in the end. i'm still not sure what Message does, etc
<aantron>
do you know exactly where the program first misbehaves?
<aantron>
if you can simplify this program progressively, while still reproducing the issue, i think that would be the most productive at least from the point of view of having me be useful
<aantron>
hmm
<aantron>
i think you need to call Lwt_main.run in this client
<dmbaturin>
It exits with 0 before it has a chance to do Message.read.
seangrove has quit [Ping timeout: 252 seconds]
<aantron>
i think you are creating the promises, but not actually waiting for them to be resolved
<dmbaturin>
Let me try. I thought since it's a one shot program, I can omit it.
<aantron>
yes
<aantron>
you should avoid exit 0 "outside" Lwt_main.run, generally
<dmbaturin>
Oh, it's not me who does it, it does it on its own.
<aantron>
what do you mean? you don't control the code that does exit?
<aantron>
actually what i am saying makes no sense, ok i am back to reading the code
<dmbaturin>
The "waiting for read" is a debug print placed just before wait_read in the do_request (I removed that clutter from the paste).
<aantron>
ok here is whats happening
<dmbaturin>
That's how I know where exactly it exits when it fails to work.
<aantron>
your match is returning a pending promise
<aantron>
sorry no, im tired and the indentation is confusing me :)
<dmbaturin>
It's a bit of a mess right now indeed.
<aantron>
ok after reading it with lots of focus, i think you need, instead of just "match !op with ..." as the top-level of your program, "let p = match !op with ...". instead of exit 0 and exit 1, Lwt.return 0 and Lwt.return 1. so p will be a promise that resolves with the exit code your program should exit with
<aantron>
then, after the "let p = match !op with ... in", "Lwt_main.run p |> exit"
<dmbaturin>
Let me try.
mbuf has joined #ocaml
ygrek has quit [Ping timeout: 248 seconds]
<aantron>
the important bit is that p doesn't just resolve with the exit code, but it resolves only after all the I/O you care about (that resolves p) is complete. "Lwt_main.run p" makes your program wait, driving any I/O, until p resolves, so that will prevent the program from terminating before the I/O completes. right now, the I/O you are scheduling is "racing" with the promise terminating as quickly as it can, which is why you see
<aantron>
different behavior in the debugger and REPL, compared to a binary
<aantron>
in simpler terms, the program never enters Lwt's I/O loop
<aantron>
promise terminating -> process terminating*
<aantron>
and the call to exit you were observing in the trace is the implicit call to exit when the program returns to the C runtime, not one of the explicit calls to Pervasives.exit
<dmbaturin>
This expression has type int Lwt.t but an expression was expected of type ('a -> 'b -> 'c) Lwt.t
<dmbaturin>
I wonder what I missed in wrapping the code in a function main () and doing Lwt_main.run (main ())...
<dmbaturin>
Then again I'm also quite tired.
<aantron>
i cant say without seeing the code, but once you work that out, your program should do the I/O
<dmbaturin>
Yeah, I'm mostly talking to myself in this regard.
<dmbaturin>
aantron: Why does it successfully do the first half of the I/O though?
<dmbaturin>
From all my tests, the request is always received by the server part.
<aantron>
lwt still starts I/O, before you call Lwt_main.run, and some of that I/O might even complete immediately. basically, all the I/O that doesn't require a call to select() (or kevent(), etc) to complete, will complete
<aantron>
so you are seeing that first I/O complete, then when the program should block to wait for more I/O, it exits instead
<aantron>
(it's really not "lwt" that's starting the I/O, in the sense of the scheduler – when you call Lwt_unix.write, etc., it can do a write(2) system call almost immediately – almost because it does some polling first). this is ocaml eagerness
<aantron>
all the scheduler does is allow you to wait on any of that first I/O you dispatched that blocked
<aantron>
(and then all additional blocking I/O afterwards)
<dmbaturin>
aantron: Thanks a lot, after wrapping it in Lwt_main.run it works as expected. I should remember to always do it even if the code is not a loop.
<aantron>
ok great. want to post about it in discuss, or shall i?
<dmbaturin>
Sure, I will.
<aantron>
thanks :)
<dmbaturin>
Why does it work correctly in the REPL and debugger though?
tarptaeya has quit [Quit: Leaving]
<aantron>
probably because the REPL and debugger are delaying your program. which REPL are you using? utop calls Lwt_main.run itself IIRC. you probably weren't calling exit in the repl, so returning a promise to utop. it detects this and calls Lwt_main.run
<aantron>
if not utop, probably just from waiting and having the promises still be in the REPL/debugger's memory
<aantron>
because the REPL and debugger weren't calling the C runtime's explicit exit when your main function returned
<aantron>
although that doesn't make full sense to me, because Lwt_main.run is necessary for resolving promises depending on I/O that blocked. i'm assuming you used utop, and it silently called Lwt_main.run for you. otherwise, some I/O in Lwt does bypass Lwt_main.run slightly, but i don't want to dig through the code to find out if that's what was happening right now :)
<aantron>
in any case, even for those I/O calls that don't go fully through Lwt_main.run, if the program exits, they obviously can't complete :)
<aantron>
so the REPL and debugger were keeping the process around long enough
<dmbaturin>
aantron: By the way, to avoid SIGPIPE in the server, is it a good idea to do wait_read with a timeout?
<aantron>
i usually ignore SIGPIPE in servers
<dmbaturin>
Is it true that if the connection is broken, wait_read will never return?
<aantron>
hmmm
<aantron>
lwt code reading time :)
<dmbaturin>
I read wait_read itself but I'd need to go deeper.
<dmbaturin>
The thread will fail is write fails with SIGPIPE?
<aantron>
i assume that the wait_read promise will resolve, and reading will give zero bytes, but i am not sure
<aantron>
i recommend testing it
<aantron>
SIGPIPE gets sent to your whole process, do you mean UnixEPIPE?
<aantron>
Unix.EPIPE
<dmbaturin>
EPIPE I'd need to check myself.
<dmbaturin>
I'm going to add a handler to ignore SIGPIPE and see what happens when a misbehaving client connects.
<dmbaturin>
This client is one shot but others will not be, so if threads don't die, it will be a thread leak since a new thread is launched for every connection.
<aantron>
that seems good. i am about 95% sure that SIGPIPE handling is not necessary for writing a correct server
<dmbaturin>
In any case I should probably handle failed writes and log them at least.
<aantron>
but i have never used wait_read and wait_write directly as a user of Lwt. however, they are used in read and write, and i have used those
<dmbaturin>
Hhm. Maybe I don't need them.
<dmbaturin>
I was under impression that trying to read from a non-readable descriptor will get me EAGAIN/EWOULDBLOCK.
<aantron>
Lwt hides that from you by default
<aantron>
IIRC wait_read and wait_write are for when you have blocking I/O calls, and you want to make them non-blocking by only executing them when Lwt says it's okay to read/write
<dmbaturin>
So the read promise will just resolve when it becomes readable even if it's not readable immediately?
<aantron>
so basically for interfacing existing blocking libraries with Lwt
<aantron>
yes
<dmbaturin>
Ah, I see.
<aantron>
i assumed you were doing something like that inside Message :)
sapristi has quit [Remote host closed the connection]
<Drup>
jpdeplaix: it's still not at the right place :)
<jpdeplaix>
fair enough
sapristi has joined #ocaml
MercurialAlchemi has quit [Ping timeout: 256 seconds]
<Drup>
(but that explanation is much better than the one in the debian page)
<companion_cube>
I'd expect everything I need to write a package, to be in the packaging guide :)
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
mk9 has quit [Quit: mk9]
mk9 has joined #ocaml
tjriles has quit [Ping timeout: 265 seconds]
tjriles has joined #ocaml
sapristi has quit [Remote host closed the connection]
<RalfJ>
AltGr: regarding that `repo` file in opam repositories... if the repository is built with opam 1, will `opam admin make` add the file to index.tar.gz?
sapristi has joined #ocaml
tjriles has quit [Ping timeout: 276 seconds]
nahra has joined #ocaml
dhil has quit [Ping timeout: 276 seconds]
al-damiri has joined #ocaml
Onemorenickname has quit [Ping timeout: 255 seconds]
tjriles has joined #ocaml
zpe has quit [Remote host closed the connection]
TheLemonMan has quit [Ping timeout: 276 seconds]
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
dhil has joined #ocaml
ziyourenxiang has quit [Ping timeout: 265 seconds]
jfntn has joined #ocaml
jfntn has left #ocaml [#ocaml]
mk9 has quit [Ping timeout: 276 seconds]
spew has joined #ocaml
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
Haudegen has quit [Read error: Connection reset by peer]
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
sapristi has quit [Remote host closed the connection]
sapristi has joined #ocaml
mk9 has joined #ocaml
cuicui has quit [Read error: Connection reset by peer]
<AltGr>
yes, it should
sapristi has quit [Remote host closed the connection]
<AltGr>
companion_cube: yes, the rewriting of the "packaging guide" is overdue :)
AltGr has left #ocaml [#ocaml]
sapristi has joined #ocaml
baboum has joined #ocaml
<tsani>
Any recommendations for a lexer/parser generator?
<Armael>
tsani: ocamllex / menhir
Jesin has joined #ocaml
<tsani>
Armael: thanks!
jnavila has joined #ocaml
jnavila has quit [Read error: Connection reset by peer]
<rntz>
hey, it appears that while ocaml has subtyping, polymorphic variants aren't subject to it in the obvious way?
<rntz>
is there any way of getting around this?
<rntz>
for example, if I write: (type foo = [ `A ]; type bar = [ `A | `B ]; let foo: foo -> bar = fun x -> x) that will not typecheck
<rntz>
is there any way of implementing the function "foo"?
<thizanne>
type bar = [< `A | `B]
<thizanne>
(or >, I never remember)
<thizanne>
should work
dhil has quit [Ping timeout: 265 seconds]
<rntz>
"Error: A type variable is unbound in this type declaration"
<rntz>
"In Type [> `A | `B ] as 'a the variable 'a is unbound"
<rntz>
(same error if I use [< `A | `B ])
<thizanne>
let foo: foo -> [< `A | `B] = fun x -> x;; typechecks but doesn't do what you want
<thizanne>
(or maybe it does ?)
<rntz>
it doesn't look like it. hold on while I pastebin.
<reynir>
rntz: let foo: foo -> bar = fun x -> (x :> bar)
<reynir>
or (x :> [`A | `B])
<rntz>
reynir: oh, thanks!
<rntz>
so :> is some kind of explicit subtyping-coercion operator?
mk9 has quit [Quit: mk9]
<reynir>
I think the more general syntax is (x : foo :> bar) btw
<reynir>
rntz: Yea, I guess, though you always coerce to a supertype
<rntz>
right, it's an upcast
<rntz>
which is fine, that's what I want, I'm just not used to having to explicitly upcast
maattdd has quit [Ping timeout: 264 seconds]
<reynir>
(sometimes I get confused what is up and what is down)
baboum has quit [Quit: WeeChat 2.0.1]
<rntz>
up/super, down/sub
<rntz>
if that helps
<reynir>
Yea
<rntz>
"The former operator will sometimes fail to coerce an expression expr from a type typ1 to a type typ2 even if type typ1 is a subtype of type typ2" uh-oh
<malc_>
Drup: all i can say that you snippet concludes with an interesting spelling of failwith
<Drup>
malc_: such state is often caused by fear of Failure
<companion_cube>
"compatibility package `stdlib` in opam" ohhh taht would be so neat
<Drup>
(On that note, let us switch to something more joyous than depression jokes)
<Drup>
like the state of the stdlib for example! :D
<companion_cube>
…
<companion_cube>
unmerged PRs jokes!
<Drup>
companion_cube: come on, #1010 is merged
<companion_cube>
it's been a little less than a year, right?
<Drup>
13 Jan 2017 for #1010
sapristi has quit [Remote host closed the connection]
<companion_cube>
ah!
<companion_cube>
a little more than a year then
jnavila has joined #ocaml
sapristi has joined #ocaml
<Drup>
and 10 Jan 2017 for the iterator one
<Drup>
ah no, that's the 2nd one, the first one is 25 Jun 2016
<companion_cube>
which is a migration of an older issue, please remember
<companion_cube>
yeah
<Drup>
come on, we might manage to have it in less than two years
<zolk3ri>
lmao stdlib
<zolk3ri>
good one
<companion_cube>
Drup: I hope so
<companion_cube>
but 2 years is still incredibly long
sapristi has quit [Remote host closed the connection]
mengu has quit [Quit: Leaving...]
Anarchos has joined #ocaml
andreas_ has quit [Quit: Connection closed for inactivity]
kakadu has quit [Quit: Konversation terminated!]
jao has quit [Ping timeout: 240 seconds]
ygrek has joined #ocaml
noplamodo has joined #ocaml
jack5638 has quit [Ping timeout: 276 seconds]
argent_smith has quit [Quit: Leaving.]
jimmyrcom has joined #ocaml
jimmyrcom_ has joined #ocaml
jack5638 has joined #ocaml
shinnya has joined #ocaml
<companion_cube>
"camlcity.org is down" lol, maybe it's been down for 1y and no one noticed :D
<reynir>
"Just asking for a friend." haha
<companion_cube>
good one ^^
<zolk3ri>
what is that even
maattdd has joined #ocaml
shinnya has quit [Ping timeout: 256 seconds]
<companion_cube>
on discuss or the mailing list
letoh has joined #ocaml
jnavila has quit [Ping timeout: 240 seconds]
kakadu has joined #ocaml
BitPuffin has quit [Remote host closed the connection]
Guest33727 has joined #ocaml
Guest33727 is now known as Haudegen
pierpa has joined #ocaml
<tsani>
I've declared a module like `module type F = sig type t ... end` and I want to write a function (outside the module) that takes F.t and does something to it (using the other functions declared in the module).
<tsani>
but writing `let f : F.t -> something = ...` doesn't work. How do I accomplish what I want?
<thizanne>
what "doesn't" work ? show a piece of code
<dmbaturin>
tsani: You mean it needs to know what the type F.t really is, or it relies on functions from that module?
<dmbaturin>
If the latter, it should work, so tell us what's your compilation error.
<tsani>
it uses only functions from the module and other global functions
<tsani>
I get 'unbound type construct Stream.str'
<tsani>
*constructor
<malc_>
tsani: stream is module type not module..
<tsani>
Sure.
<tsani>
Is it not possible to program against an arbitrary module with a given module type?
<tsani>
(That's what I was hoping for.)
<Drup>
tsani: you can, by writing your code inside a functor
<tsani>
hm
<tsani>
I guess maybe I'm approaching this from a completely wrong angle. I'm fairly new to ocaml (my background is in Haskell). If I wanted to provide some default implementations for functions inside a module signature, how should I proceed?
kakadu_ has joined #ocaml
kakadu has quit [Ping timeout: 276 seconds]
maattdd has quit [Remote host closed the connection]
<Drup>
you don't :)
<tsani>
haha
<tsani>
Gotcha :)
<Drup>
tsani: I suppose you are trying to emulate a typeclass, what's the use case
maattdd has joined #ocaml
<tsani>
I'm just messing around right now to familiarize myself with the language. I'm implementing a parser, and I'd like my parser module to be parametric in the stream type. So I implemented a Parser functor that takes a Stream.
jnavila has joined #ocaml
<tsani>
It's always possible to implement `isempty` by just checking whether `uncons` worked, so I figured I'd have a default implementation using that strategy.
<tsani>
and for streams that are more intelligent (e.g. track a their position inside the input as well as the length of the input), they can implement isempty more efficiently
<malc_>
tsani: curious, why have you decided to try ocaml?
<tsani>
malc_: I'm more or less forced to use it haha
<tsani>
malc_: I've started as a grad student and the programming language I'll be working on is implemented in ocaml
<tsani>
But so far I like it. In particular I think modules are the bomb :)
jnavila has quit [Quit: Konversation terminated!]
<malc_>
tsani: coq? compcert? haxe?
<tsani>
malc_: Beluga
<malc_>
tsani: modules are the bomb, module types bite you...
<justin_smith>
I know OO is unpopular and all but if what you want is a default implementation that is open to extension that overrides some behaviors while keeping others from the parent, objects are decent at that.
<tsani>
justin_smith: huh
<tsani>
I've never once even seen OCaml code that uses objects. I should read up on it.
<justin_smith>
it's where the o from ocaml comes from
<Drup>
tsani: imho, that's a bit over-engineered, but you can provide a functor that extends a minimal argument into a complete one
<tsani>
right
<tsani>
Drup: yeah that does sound a bit much
<Drup>
it's actually common to do that for functors with really complicated arguments
<bartholin>
why is noone using objects
<Drup>
bartholin: because modules covers 80% of their use cases, but better
<justin_smith>
inheritence makes for very bad designs usually
<malc_>
bartholin: i'm using objects
<malc_>
ocamlopt uses objects
<malc_>
so there
<malc_>
2 is a crowd
<Drup>
tsani: hey, I asked Brigitte Pientka about a postdoc position last year =')