OCaml: Polymorphism
haifengl.wordpress.com
haifengl.wordpress.com
opam install cohttp
> command-line tool opam install cmdliner
> Go has a great batteries-included standard library.OCaml doesn't, but there are good stdlib replacements, and its package manager is really nice.
When requested to install a second package with overlapping dependencies as a previous package, it would try reinstalling all dependencies, including previously installed ones, and would fail.
That is, in my book, an epic fail for a package manager, let alone a supposedly >1.0 version (if that even means anything today). I'm still annoyed about that. Searching online found recommendations to get the latest version from Github.
1.2.0 has since been released and included in Debian. I keep meaning to give it another go, but I must admit being wary after that first experience.
This was unfortunately a mistake made by upstream Debian. Rather than reimplement the constraint solver badly, we use the Aspcud external solver. An upgrade of Aspcud changed its command-line interface, and OPAM 1.1.0 wasn't upgraded to OPAM 1.1.1 at the same time (which detected the new version of Aspcud and worked with it).
A similar issue (to do with the libdose interface) has been in the Ubuntu package ages and not addressed by upstream despite a detailed bug report: https://bugs.launchpad.net/ubuntu/+source/opam/+bug/1401346
> Searching online found recommendations to get the latest version from Github
What else could we recommend?
It's really frustrating to know that a source-compiled OPAM works fine, but that the packaged binary versions are broken and our only recourse is to wait six months for the next OS release of Ubuntu. On the bright side, the OPAM 1.2.x series has been very stable and is now making its way upstream, so this is hopefully a temporary issue.
I'm really grateful to everyone doing all this work. This is a typical example of the kind of "excitement" mixing distro package managers and language package managers can lead to. The only recourse is to file a bug, maybe provide a backport if feasible, and move on -- and have everyone (package maintainers, distros) be a little wiser, and (hopefully) everything working on the next release.
Anyway, I see I have opam in my ~/bin -- so clearly I've compiled it myself at some point. No wonder, as I'm still running stable on this laptop:
https://packages.debian.org/search?keywords=opam&searchon=na...
Maybe there should be a note in the wiki about it, although it should be resolved when jessie is out?:
(Yeah, I know, it's a wiki. I could just add it. I don't feel quite confident enough to go and clutter such a short little page, though. Different if there's a page where "someone is wrong on the internet".)
In that particular timeframe (Sept/Oct 2014), the Debian maintainer just hadn't uploaded a newer version of the package: https://tracker.debian.org/pkg/opam
It's a pity, because I think Debian's Experimental section would've been ideal for this.
I've been using Debian long enough that I'm a bit ashamed not to be able to package things on my own yet...
Haskell's cabal has gotten better; it's still easier to run xmonad/mobar from Debian packages, but at least cabal with packages/cache in ~/.cabal kinda-sorta works.
It seems the path towards package managers that both work well and work well with stable/distro packages is long, ardous and filled with repeating the mistakes of others. Npm seems to have learned a bit from python - if you stay away from -g(lobal), it tends to mostly just work (not sure about c/c++ dependencies - for better or worse a lot of npm packages are mostly pure js).
Python with virtualenv works very well, except for a few hairy c-heavy packages (pygame, sci-py) - but running "sudo pip install ..." is a recipe for disaster (or a mongrel, unpatchable mess). Keep to virtualenvs and you can stay mostly sane (or use the isolation provided by buildout -- preferably in concert with virtualenv).
I was lamenting that Opam 1.1 wasn't dealing with a trivial package installation situation. I mentioned Debian to indicate that was the source of the version I was using, implying that there may have already been a newer version out there that I could've been using, but then explicitly saying that 1.1 should've dealt with the situation in the first place.
FWIW, I definitely agree with the terrible situation of language package managers in general. I use Python sporadically, and I'm always scared of running pip. Virtualenv I'm very unhappy about because, while it definitely fulfills it's task marvelously, I think it shouldn't even have to exist in the first place! Why doesn't core Python deal with the problem itself, searching for dependencies in the main script's subdirs, the user's libdir, and lastly the system libdir? Admittedly, I don't know the intricacies of the Python ecosystem that prevent that.
Well, it's all connected. A package will need a certain version of ocaml itself, it's standard-lib (or alternative) other libs it needs. These will all depend on various c libraries to a certain degree. So if opam started re-downloading a lot of dependencies that should be available, that sounds like either a) some part needed a newer version, or needed to recompile with different flags, or b) opam didn't find the dependencies installed by dpkg.
Python and Debian go pretty well together, probably partly because a few core utilities use python. So with some creative use of "apt-get build-dep" you can usually get the needed c libraries that things depend on, and so have a better time installing things that need c-code in virtualenvs.
I'm not sure how you think linking to (possibly rapidly moving) c-libraries from a language that runs across a wide range of operating systems and versions should work, if not with something like virtualenv (or buildout). There will, I think, always be a need for packages that are moving faster than stable distributions can/should keep up with -- and there needs to be a sane way to deal with that.
With c code, you can stuff things in /usr/local -- but keeping that in sync as you patch the main os (and do dist-upgrades) and as you need to patch the various libraries/dependencies... is challenging. And that's just for c. When you put another layer on top (ruby, python etc) -- it doesn't really get any easier.
One option is to go the way of bsd ports/gentoo -- but there are at least two issues/trade-offs with recompiling everything from source: 1) if you're mixing and matching versions and compile-options, you quickly end up with unique binaries. Which is to say, binaries that no-one else have tested before you. Granted any bugs you encounter will be in the program and/or the compiler -- but you'll have the joy of finding them. In production, most like. 2) It really doesn't make much sense to recompile "all the things" if the goal is to end up with the same binaries anyway.
cohttp wouldn't install, due to a dependency, conduit, not installing properly[1] -- possibly due to the old libssl-version (with backported fixes) in Debian stable. I do have a sid and a jessie chroot -- but I've yet to try running it there -- part of the point of chroot is automounting of the home folder in the chroot(s) -- and that'd give me a .opam that wouldn't work under stable; or I'd have to jocky around with altearnative .opam folders...
[1] An error along the lines of:
File "lib/conduit_async_ssl.ml", line 28, characters 18-108: # Error: This expression has type # Ssl.Connection.t Deferred.Or_error.t = # Ssl.Connection.t Core_kernel.Std.Or_error.t Deferred.t # but an expression was expected of type unit Deferred.t # Type # Ssl.Connection.t Core_kernel.Std.Or_error.t = # (Ssl.Connection.t, Error.t) Result.t # is not compatible with type unit # Command exited with code 2. ### stderr ###
https://github.com/mirage/mirage-www/wiki/Pioneer-Projects#c...
[1] https://realworldocaml.org/v1/en/html/command-line-parsing.h...
Oh come on, it's not that bad, it's just minimal. Usually I can get pretty far without having to reach for something like Batteries. That's a good thing, especially when writing reusable libraries where you don't necessarily want to pull in an entire stdlib replacement.
This tends to happen over time, as the community naturally converges on certain libraries, but it's rather opaque for a new user as to what those are. In some cases, you end up with two options and then life is a little more complicated (cf. async and lwt).
Things people are used to:
- `let` keyword (rust, ES6)
- pattern matching (generalization of ES6 destructuring)
- function first, HOF combinators (ES5 functional literature)
- tuples (python)
A few years back, all these would appear as black magic...https://realworldocaml.org/v1/en/html/prologue.html#why-ocam...
But the one I like the most is Parametric polymorphism because it tends to make algorithms generically available to anything.
And the one I like the least is subtype polymorphism due to it's reliance on inheritance with all it's attendant problems. The exception being for the sub-genre of "interface" polymorphism. Which doesn't really exist in C++. However when it does exist such as in languages like Go, Java, or C# then it fixes almost all of the problems that tradional subtype polymorphism has by taking inheritance completely out of the picture.
1. In C++, the compile error messages with templates are so hard to navigate. 2. In OCaml, sometimes we need pay attentions on the performance.
This is just a fancy word for naming stuff consistently instead of trying to shoehorn constructs to have some kind of formal language-aware relationship via abstract methods, overloaded methods, etc., which sometimes just increases coupling/complexity with no real benefit.
Perhaps I'm dreaming. But it sounds like useful to me, as there are so many languages that are almost similar, and yet are slightly different in the way they handle typing and things like polymorphism. It would seem to me that those languages could all share a common base.
See http://search.cpan.org/~ether/Moose-2.1403/lib/Moose/Manual/... and http://search.cpan.org/~ether/Moose-2.1403/lib/Moose/Manual....
Competing type systems, competing Object systems, and enough internal run-time rewriting to do whatever it is you want.
See also http://search.cpan.org/~smueller/Filter-Simple-0.91/lib/Filt... for a simple rewriting filter, and the Acme namespace for all kinds of fancy experiments.
That said, I don't expect to see a language that does all the things you listed at the same time, since type systems are all about tradeoffs between expressivity and complexity and there is an upper bound in how much complexity a programmer can handle. There are also a lot of other tradeoffs that you need to think about: do unproved assertions get converted to runtime checks or to compile errors? Can you implement that efficiently? How will type inference work? Is it OK to design an unsound type system? etc etc.
I can give you some pointers if you want to look for something more specific.
But the idea of "layered" language is nice. In Scala, many features are not really from language itself, but from libraries.