Try OCaml
try.ocamlpro.com
try.ocamlpro.com
What do you think?
Sketch is really awesome, and serves different purposes. Domical is just an interpreter for the iodide notebooks, which are designed to be portable and execute all kind of languages: js, python (those crazy folks compiled the full interpreter and f numpy in WASM) and now OCaml.
I can see that sketch has really a lot more features.
A key feature of iodide is its simplicity and portability: the whole notebook is written in a readable format looking like markdown and called jsmd. Take a look at the source code of the page to better understand.
So definitely we have a lot to share on our respective projects, even if I am not one of the main contributors of iodide (I just did the OCaml part).
If you want to continue this discussion, my email is on my homepage :)
If you want to try F# w/o any installation, try it in Jupyter on Azure Notebooks:
https://notebooks.azure.com/Microsoft/libraries/samples/html...
Browse w/o loggin in, or if you want to edit/run/..., sign in, click Clone, then play around.
It's all free.
Cheers.
Maybe you could word it as native `ocaml` interpreter instead? Ocaml can compile to machine code.
"The OCaml native-code compiler, version 4.07.0"
The online version is basically a top-level exucuted by the js engine of your browser, and it is more performant than its equivalent executed natively.
It had -- in 2.5s :-)
For the performance we really have to thank the folks of js_of_ocaml!
What I'm looking for is the ability to produce native binaries without Cygwin. I just checked without installing anything and it appeared as though OCPWin was still the choice, but it's been stuck on OCaml version 4.01.0, which was released five years ago. I know that OPAM is pushing toward a 2.0 release very soon and I didn't know if that was going to coincide with a stable OCaml/OPAM release on Windows, which would fix my problems. Does anyone have an idea?
I'm looking forward to the day when I won't need Cygwin even in the build environment. Since the OCaml compiler itself works fine on Windows and modern build systems like "dune" are also Windows-friendly I'm fairly optimistic this can happen soon. I think it'll mostly be a matter of removing accidental Unix-isms (like unnecessary use of symlinks) in the build scripts.
I didn't know about dune. Looks neat. Is this meant to be used in conjunction with opam?
There are some interesting experiments combining the two more closely -- take a look at "duniverse" https://github.com/avsm/duniverse which is a prototype system which would use opam to solve package version constraints and download the sources, allowing dune to build everything at once. The nice thing about this is that you could patch one of your dependencies and then dune will be able to perform an incremental build, as if all the code was in one big project. I'm personally hoping this will help speed up Mirage development as it can be time-consuming to propose a change to an interface and then find all the places that need changing (a cost of having lots of small repos versus a big monorepo)
It’s not Microsoft’s primary language and unfortunately sometimes shows but now it’s there.
https://docs.microsoft.com/en-us/dotnet/fsharp/get-started/g...
https://notebooks.azure.com/Microsoft/libraries/samples/html...
Browse w/o loggin in, or if you want to edit/run/..., sign in, click Clone, then play around.
Cheers.
I discovered it when I was reading a lot about domain driven design, and I stumbled upon a talk by the author that kind of blew my mind:
"Domain Modeling Made Functional" https://www.youtube.com/watch?v=Up7LcbGZFuo
In addition to linking to other parts of the documentation, it links out to other third-party learning sources.
Then there is "Programming language Concepts" by Sestoft - which, while being a language book, at the same time exposes lot of beautiful patterns how to exactly use F# for data munching.
Then, thirdly, Jon Harrop's "F# for scientist" is a great introduction for us that have a penchant foe writing numerical code (graphics or whatever). It's a great companion for the Expert F# as it shows how to use F# effectively in place of sonething like C++ or fortran.
I click the last one and advance a step before I can comprehend what this command did or read any context. Breaks flow completely... And I'm just able to be fine advancing manually once I feel I'm done with the current step.
Other nits:
* show the ;; in the step code snippets, at least at the beginning - else you may be confused fast if you hack around in the "terminal"
* add a 'run this snippet now' button to the code snippets, a small green triangle or whatever those IDEs are using nowadays, allows to copy of examples either modifying before execution or - like me - paste them in a "real" OCAML REPL I have on my desktop.
don't get me wrong, the site and idea is nice, those things just irritate me, almost irrationally, from an UX POV.
OCamlPro is heavily involved in the development of Tezos and a big part of the reason I invested in it. One of the main selling points of Tezos is formal verification, which OCaml (being a pure-ish functional language) was instrumental for.
Regardless of the future of crypto (fad or world changing) if it's handling money or other assets it should be done safely. This is step in that direction.
OCaml is also used at Bloomberg and Jane Street.
It's a pity that functional programming and formal verification aren't enough to overcome selfish and destructive founder behavior.
It was __very__ amusing to play with Variants, Pattern Matching and Units. If programm compiles - it almost always just works. It's an indispensable tool to play around and get more ideas how to write a better programs.
And it was disastrous in __everything__ else. Installation and compiler bugs. Terrible tooling. Terrible code packaging. Terrible Javascript interop. Painfully archaic syntax. Sometimes extremely esoteric compiler errors.
After a week i thrown out all the code and rewritten it using Typescript. Won't ever use new languages on projects with deadlines, no matter how sweet evangilists talks are.
I've picked up ReasonML about 3 months ago and experienced almost none of the issues you described. It's still a little rough around the edges compared to for example Elm, but the tooling, packaging, Javascript interop etc are really good IMO.
We even used Reason for writing ObjectiveC/Cocoa through CocoaScript (a Javascript-to-ObjC bridge), thanks to Reason/BuckleScript's excellent Javascript interop.
The language and compiler is rock solid - it has to be because it has been worked on for over 40 years from the days of ML. For the last three years a team of people including Hongbo Zhang, Jordan Walke, Cheng Lou and others have been actively working on Javascript tooling for OCaml, and it is an absolute pleasure to use today.
[1] Protoship Codegen - https://youtu.be/hdww16KK8S8
I can never understand this claim when people make it about languages like Haskell and ReasonML.
How is the compiler catching your logic bugs? If you write 'a + b' and you should have written 'a - b' the compiler isn't going to catch that in either of those languages. It'll compile but it won't work. Do you never make these kind of logic bugs?
Yaron Minsky (Jane Street, largest OCaml user) coined the term "make invalid states unrepresentable" to explain how ADTs help in enlisting the help of the compiler to help us express our intent correctly, and Richard Feldman (NoRedInk, largest Elm user) has given an absolute gem of a talk that dives into that idea with relatable, concrete examples.
It is titled "Making Impossible States Impossible" and should clarify this concept nicely. https://www.youtube.com/watch?v=IcgmSRJHu_8
I find that in Python - probably any dynamic language - a lot of the tests I write are just to make sure the pieces fit together. It's too easy to write well tested units that don't work together because of a misplaced argument or something at the interface. That type of testing is largely not needed with static typing.
Also, when I create a data structure in Python my mental model of what it means and how it relates to other parts of the program can be kind of fuzzy. Which means the pieces may not fit like I think they do because I missed a detail.
But a strong static type system forces me to clarify my thinking much earlier in the coding process than in a dynamic language. It encourages me to encode more of my mental model into the code and that allows the compiler to double check me.
It's kind of like spell check but for design.
1) If it compiles, you won't get a "undefined is not a function".
2) If it worked, you changed something and looked at all the places compiler told you to look at, all the code it didn't tell you to look at is very likely to continue to work corrrectly.
(1) is a very convenient feature and easy to advertise, but (2) is what makes people jump around and tell that everyone should use ML: it allows to be not afraid of changing something in the first place.
I have even less experience with OCaml, but my gut feeling is that it should be about the same in this respect unless you let mutable state run wild.
It's more about programming declaratively, functional, as well as strong types which allow you to be very expressive. My experience with F# is similar, if you can get you code compiled, it almost always just works as you expect. But this doesn't mean that you can avoid writing tests though.
This is a good read about it, https://fsharpforfunandprofit.com/series/designing-with-type... by Scott Wlaschin.
"Modern" dev is not about writing algorithms, it's about sewing together many different frameworks/libraries/technologies.
I'm probably biased as most of my experience is in webdev, but other domains seem to have the same issues (probably not to the same extend).
The trend I see growing is towards microframeworks, smaller libraries, less dependencies (or if you have some, a small opinionated set of them), are more doing it yourself -- I think this phenomena, more simply put and was championed by go -- is to "just write code"
I am enjoying "just writing code" far more than my days as a library and framework glue person, and it is a lot easier to have other devs ramp up, as an added bonus. "Here, read this simple code to understand what's going on and then add your code" versus "here, study these docs, learn this framework, install all these dependencies then learn our coding style within the framework to understand what's going on, then add your code"
Gary Bernhardt kind of captures my sentiment these days with regards to massive libraries and frameworks these days in this thread nicely: https://twitter.com/garybernhardt/status/1037101314939875328
I can say that this effect seems very real. I think the reason goes beyond those shallow type mismatch errors I often make. Part of the reason, I think is, the correct program becomes clearer to write compared to the erroneous programs you could have written if you use the type system. In other words types can make some of the erroneous versions cumbersome, or at time, impossible to write -- but good luck mud wrestling with the compiler till its convinced.
I will strongly encourage that you try it and dont be discouraged. This really needs to be experienced first hand to be convinced.
However in languages with rich type systems you can do Type Driven Development, which reduces the area space for many kind of errors.
Basically a simplified version of dependent typing, where one makes use of the type system to represent valid states and transitions between them.
For example, one can use ADTs to represent file states, with the file operations only compiling if the file handle is in the open state.
Doing so in other programming languages always makes me nervous, in C an innocuous change could introduce some memory corruption bug because you broke an implicit invariant of the code, in Python it could raise a type error when called in an unexpected way. To review a pull-request you have to look usually at the entire file (or sometimes the entire project), and even then you can't be sure.
As for the logic bugs: that is what tests are for.
I have spent an embarrassing amount of time troubleshooting a < that should have been a > (in F#) where it actually resulted in a very subtle defect. I'm not aware of a type system that works have prevented this and yet,I do strongly agree with the assertion that in more strongly/statically typed language, "compiling successfully = very likely to run correctly."
It doesn't, and I agree with your sentiment. IIRC, type-related errors account for ~10% of bugs.
If (and only if) types are tied into your tooling ecosystem (for example, an IDEs that uses that info to full extent to aid in code completion, refactoring, code analysis etc.), they are very useful.
This sounds implausible to me unless they're only counting bugs that have slipped through QA and have later been fixed in production. In my experience the compiler catches maybe 95% of my errors I write. Most of those would be caught by my unit tests or my manual testing, and a few more would be caught by the QA team, but it's much nicer and faster to get notified about them immediately.
I never thought of that, but that is a really valid point. I guess that is why Ruby/Python are so popular as most of the problems programmers run into in production aren't type problems.
I was tasked with adding proper honorifics for Japanese speakers (it's complicated in the general case, but I was just getting as far as "San"). I wrote some straightforward PHP code to implement this feature, but of course it broke in production for some nontrivial percentage of requests. Why? Because the string I was adding the honorific to wasn't always a string. WTF? What is the proper course of action when strings aren't strings? Well, in this case the answer was a run-time type-check guard on the code I had added.
Keith Adams, my esteemed colleague, likened this to "dogs and cats living together", perhaps revealing a fondness for simpler days when Ghostbusters trod the streets. Keith may not have gone as far as lauding OCaml's type system in those dark early days, but I will do so now (and perhaps he would too).
http://www.arewelearningyet.com
Though I am pretty confident that Rust will get there in a few years.
There's plenty of Rust-talk here on HN, and plenty of numerical/ML talk, but they seems like very non-overlapping user groups. Particularly curious why you chose Rust over Julia or even Go, given that (to an outsider) both seem to have a lot more people excited to do ML with them.
I used to use Go when Rust 1.0 was not out yet. I was generally happy with Go. My primary gripes were:
(1) C calls are relatively expensive, which is ok for long-running functions (e.g. run a Tensorflow session), but now nice for calling C code in a tight loop.
(2) Go gives no control over memory alignment, while C++ machine learning libraries generally prefer alignment on a certain boundary. IIRC Go aligns slices on a 16-byte boundary and Eigen (which is used on Tensorflow) wants arrays that are aligned on a 32-bit boundary. I don't know if this is still true, but Tensorflow used to make a copy of an array that was incorrectly aligned. So, you had to resort to doing allocation in C and then using the SliceHeader hack to give the array somewhat of a native Go interface. But since the backing memory is allocated in C-land and Go does not have general destructors (only defer), you have to rely on finalizers to do deallocation (which provide no guarantee when they are called) and/or relying on the user to explicitly call a resource deallocation method. Of course, that does not really gel well with slices.
(3) Rust + LLVM optimizes far better than the Go compiler. This is not a secret. Parametric polymorphism provides much more opportunities for inlining than dynamic dispatch and LLVM inlines and optimizes aggressively. I spent a lot of time compiling compiled Rust and compiled Go assembly and the differences are quite shocking. That said, the Go people have been working on better inlining as of recently and with the possibility of generic in Go 2.0, things will probably get better.
That said, I think that in larger teams, Go may still be the better choice. It is easier to pick up. It is harder to make code that is 'too clever'. It has good packages, such as gonum, which provides a lot of linear algebra functionality and functionality for plotting. Tensorflow has direct support for Go, including for building computation graphs, etc.
I would love to try Julia! But I did not progress much beyond the first few steps of the tutorial ;). I think I would like it much for quick exploration in the vain of Python + numpy.
One big reason that numerics aren't the best in Rust right now is the lack of integer generics. Some people are waiting for that before bothering to write libraries, as they'd change the libraries so much anyways.
My assumption was that anything else would be painful, but I tried some ScalaJS after one too many frustrations with TypeScript and was pleasantly surprised at how easy it all was.
Nowadays things are quite neat with opam/dune/odig stuff. You can install packages, generate readable docs for them, just like in rust. For the rest api you could just take any existing framework, I think, e.g. [1] [2].
You should also consider that OCaml is a language, which for a long time was intended for a different kind of projects (yeah, webdev is not the only programming domain, shocking), so the direction was dictated by Coq and similar project devs rather then webdevs. Now facebook and other companies change the state of affairs.
I can only imagine how many bugs I would type at this stage of my career after being used to [] for arrays but forgetting the pipe, and getting a list instead. It's also very difficult to type.
Luckily, the compiler would catch this anywhere you tried to use a list where an array was expected.
> how common it is to use lists versus arrays?
Lists are far more common in day-to-day usage. The language even has native syntax for list consing and destructuring, which is useful for pattern matching.
OCaml arrays do have their place though, if you have a fixed number of items and need random access. Float arrays are also specialized, their elements are unboxed and contiguous which helps with performance for certain types of number-crunching applications.
I was thinking quite the opposite, I admit I don't know much about OCaml yet but I was very interested in trying ReasonML. Anyways, I would think you would use an array when you need sequential access and potentially help locality of reference when doing some number crunching? OCaml arrays are random access?
Yes, that's what float arrays were specialized for. From a quick glance at the OCaml compiler code, you might also get effective locality with other unboxed types (ints, chars). Boxed types will likely require an additional lookup even if the values are allocated contiguously. But if you're at the point of being concerned with memory access patterns, then bigarrays will probably work better.
If all you need is sequential access, then a list is much more convenient to use.
I'm not sure how all this translates to ReasonML though, as the JS runtime is very different.
When I was learning OCAML and bought the book, Jon actually found some code I had posted on my website and sent me some advice about how to make it more idiomatic. He even rewrote the first one of my functions to show me how.
I think that the days where one language gets momentum and becomes "the" language for some scientific computing task are gone. No doubt Julia does have momentum. However, these days interoperability is rapidly improving, and we are rapidly moving to an equilibrium where you can more or less choose your own language and not worry too much about it being the "right" language, because you can call libraries written in numerous other languages. I certainly hope that's where we're going.
In terms of prototyping algorithms, MATLAB/Octave still seems to be the best choice. We have access to an enormous number of builtin routines that help diagnose what's going on when an algorithm breaks. That's not to say other language don't, but the ability to set a single dbstop command and then run some kind of diagnostic like plotting the distribution of eigenvalues with d=eig(A); plot(real(d),imag(d),'x') is amazing and saves time. There's also a very straightforward workflow to run the debugger and then drop into gdb in case the case we need to interact with external libraries.
Now, certainly, MATLAB/Octave is weak, in my opinion, for generating larger software projects that need to interact with the rest of the world. This includes things like network connections, GUIs, database access, etc. Alternatively, sometimes a new low level driver needs to be written, which needs to be very fast. All that same, that ecosystem seems to be much better in languages like C++ and Python. Though, I've been experimenting with Rust as an alternative to C++ for this use case. At this point, if I have trouble with the algorithms, I can run it in parallel with the MATLAB/Octave to diagnose how things differ.
Coming back to Julia, where is it supposed to fit in? To me, there's a better prototyping language, production language, and bare metal fast language.
I will make one last quip and that's the licensing. Frankly, the big advantage of MATLAB is that it provides license cover. Mathworks has obtained the appropriate licenses for your expensive factorizations and sparse matrix methodology. Julia has not and they remain largely under GPL:
https://github.com/JuliaLang/julia/blob/master/LICENSE.md
Look at things like SUITESPARSE. Practically, what that means is that I can deliver MATLAB code to my clients and I don't have to disclose the source externally due to GPL requirements. Now, maybe they choose to run Octave. That's fine and then they can assume the responsibility for GPL code. However, for me, I maintain a MATLAB license and that gives me coverage for a whole host of other licenses in the context of MATLAB code and that makes my life vastly easier than if I were to develop and deliver code in another language.
As far as fast bare metal languages go, you can write extremely general optimized matrix multiplication libraries in Julia. For matrices that fit in the L2 cache, I achieved performance similar to Intel MKL, but with far more generic code.
https://discourse.julialang.org/t/we-can-write-an-optimized-...
Writing a kernel in C means using SIMD intrinsics, where function names and types differ for every vector size, and then different numbers/sets of calls for each kernel (you'd want several sizes per architecture). Compare this to Julia, where parametric typing and multiple dispatch mean you only need one set of functions, and using an @generated function will generate whatever kernels you happen to need at compile time.
Looking into the future, awesome projects like Cassete speak to the potential of what's possible:
https://github.com/jrevels/Cassette.jl
Cassete promises to let you do anything from getting automatic differentiation for arbitrary Julia code, even if it is strictly typed and buried in a chain of dependencies of the library you're using and written by someone who never imagined the idea of autodiff, to injecting custom compiler passes.
Also, while I haven't tried it yet, many seem to like: https://github.com/timholy/Rebugger.jl
Julia is more promise than practice right now, but that's largely because of just how much it promises. I (and many others) think it has done a great job delivering so far. That's why there's excitement, and why many are starting to embrace it.
This is not true for any recent, competent compiler. I can write a template function in C++ code with a regular loop over arrays and it gets vectorized withSIMD instructions automatically according to architecture. Sure, it’s not JIT but it still never requires intrinsics
The relevant comparison here is against matlab. If you want to spend two weeks writing and debugging an optimized version of matrix mult for a custom type in c/c++, that's your business, but one can do it in a day in julia and be fairly confident it will just work.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86625
because unless I use SIMD intrinsics, while the code is vectorized, there is a high density of unnecessary move instructions resulting in dramatically slower code.
Using SIMD intrinsics in C avoids that problem.
https://github.com/JuliaLang/PackageCompiler.jl
Which really for me they are good enough, I don't remember the last time I cared about producing a .a/.lib file for delivery.
Counter question: Can you in 24 hours ship a binary library built in C or C++ that in guaranteed to work on ARM, x86, and also detect NVIDIA or AMD GPUs and use those for acceleration as needed?
Of course, most programmers don't know what generic programming even is. However, a lot of libraries these days utilize it in order to get different precision and all of that, which is why I think Julia will at least become a language of libraries since not too many people can invest so much time in C++.
Where do you get this from? You’re coming off far too aggressive. Metaclasses or AST rewriting decorators are parts of Python. I know they don’t fit your use case but you don’t need to set fire to multiple ecosystems because they don’t invoke a full blown compiler for every line of code.
I thought it was either solved by adding function signatures based on actual usage, or “boxing” the argument (which I guess is just dynamic at that point)
Why would you ever see the combinatoric explosion in an AOT implementation?
As for boxing, boxing works but it's slow. The developer of LightGraphs.jl tried using Swift for awhile but went back to Julia when he realized that actually using generics in Swift is really really slow because they do this boxing (your code is generic! But...). To finish the story, he tried Go a bit but generics in Go... he went to C++ but templates but they were difficult to use and the compile times were too long to be anything close to interactive, and has done extremely well over the last few years in Julia (though it is admittedly missing some tools for (partial) AOT compilation and building binaries, but these tools are in development).
"Also exciting - we only have 27k signatures right now, and removing all the ones taking row vectors reduces that substantially to under 10k. That seems doable pretty easily, and we can convert without performance penalty between row and column vector seamlessly (I believe)."
https://discourse.mc-stan.org/t/compiling-the-math-library-i...
Those sound like big numbers to me! That's a real problem that DynamicHMC.jl doesn't have to worry about, for example.
I think Stan's autodiff is faster than ForwardDiff.jl/ReverseDiff.jl (other than Stan models regularly taking several minutes to compile), but I'm betting on Cassette-powered Capstan/Zygote getting there in the next few years.
[1] http://www.euclideanspace.com/prog/scratchpad/spad/index.htm
Although you may not like it, it serves a purpose and it's one tool among many.
Some groups use Typhoon:
Opal-RT is built on MATLAB/Simulink, which is how it came up. Anyway, what real time simulators do you use?
In power system planning people use PSS/E, PowerWorld, PowerGem TARA, and a variety of other loadflow tools for powerflow and N-1. They don't generally use much real time data and instead use models ranging from 1 year to 20 years in the future. There are also another dozen vendors here selling specialized products that do everything from Voltage Stability to Transient Stability to optimization of topology and fault analysis. The breadth is very wide. You might use multiple vendors with some degree of product overlap because you like vendor A's powerflow functionality and graphics, while vendor B has the best dynamics on the market.
I'll have to check out the links you've sent as I've never heard of these two products and I try to keep my ear to the ground, but it is a huge software market and I don't monitor Europe's market as well.
Edit:
Just checked out your opal-RT links and yes that is real time power systems software, just not the kinds of real time analysis I typically use and think of. This seems closer to PMUs (phasor measurement units) which instead of 4-second SCADA data use something to the tune of 60 samples a second (that's a lot of data).
Do they have ML libraries to compete with PyTorch and Tensorflow? How about geometric calculations such as Voronoi and Convex Hull? Can it handle noneuclidean geometry? Is there a good library for network analysis? GIS? Do they have a symbolic computation library to stand up to SymPy?
If Julia can answer Yes to all of the above, then maybe it's worth checking out.
Is there a mature option for calling Julia from Python?
He’s mainly converted to F# if I remember correctly. He was often in flamewars on OCaml mailing lists about multicore support.
There is a bit of hype around Julia but it’s use in the real world is a rounding error compared to Python, R, MATLAB, FORTRAN etc etc. I might look at it again in 5 years or so. OCaml never gained any significant traction in scientific or numerical computing.
You can try F# on https://notebooks.azure.com for free
Seconded, it's an awesome book!
Nor is it safe to allow implicit conversion in general, but F# shows that you don’t need separate operators for floating point. You just need a compiler that refuses to implicitly convert data types, as F# does, so you must use explicit conversions and type suffixes if you want to mix data types. If you manually convert, then on your head be the consequences.
This is not legal F#:
let x = 1.0 + 1
But both of these are legal: let x = 1.0 + 1.0
let y = 1.0 + float 1
F# doesn’t even let you mix single- and double-precision FP: let x = 1.0f + 1.0 // ILLEGAL
let x = 1.0f + float32 1 // legal let add x y = x + y
The proper solution for ad-hoc polymorphism is either dynamic dispatching (aka oop solution) or type-classes or OCaml's modular implicits, not ad-hoc monkey patches like that. And I find (+.) fine since float addition is not an arithmetic addition.If you don't call it, F# simply guesses "int -> int -> int". If you pass a float, you get back a curried function taking float and returning float. Now that the "add" function's type is known, you now can't pass an int: that's now known to be an error.
Seems sensible to me. No problem.
Haskell or Rust are the same incidentally: while the same "lexical" operator is used all the time (`+`), numeric additions are defined for two values of the exact same concrete type e.g. in Haskell you can add two Int or to Float or two Integer, but not an Int and an Integer, or an Int and a Float:
Prelude> (1::Int) + (1::Int)
2
Prelude> (1::Integer) + (1::Integer)
2
Prelude> (1::Float) + (1::Float)
2.0
<interactive>:6:15: error:
• Couldn't match expected type ‘Float’ with actual type ‘Int’
• In the second argument of ‘(+)’, namely ‘(1 :: Int)’
In the expression: (1 :: Float) + (1 :: Int)
In an equation for ‘it’: it = (1 :: Float) + (1 :: Int)So in ghci:
Prelude> let x = 1 + 1.0
Prelude> :t x
x :: Fractional a => a
Prelude> x
2.0What I was intending to show occurred because I engineered the example to show it, yes, that was the entire point.
> Without the type annotations it would have worked just fine
Without the type annotation it would have been in an actual codebase rather than the REPL, and that codebase would have been typed.
> because the (+) function is polymorphic in the Num typeclass, and because literals are overloaded such that the literal 1 will have type Fractional a when type inference calls for it.
Which does not contradict my point at all.
> So in ghci:
Which works because (drumroll) both operands are of the same Fractional type. Which is the entire point of my comment: Haskell does not allow adding numbers of different types with one another any more than OCaml does.
(+.) is the equivalent for floats: 1.0 +. 1.0
In short: if you need any operator for floats, and you know how to write it for ints, add a dot.
The reasoning is that it's hard to define the semantics of mixed expressions and explicit conversions clarify what needs to happen.
I've since grown to like it, because the only times I've been caught out by it is when I've made a mistake or I've forgotten I was working with floats.
Don't let the syntax put you off Ocaml, because there is some reasoning behind it. It's a multi-paradigm language that has a lot of powerful features.
React has made the probability much higher. Reason is kinda like JS the good parts + Immutable JS + Typescript + Redux. Plus it works well with React. If your team is using React there's a good chance you'd get a benefit from implementing Reason in a few places with little risk.
Because it is "just Ocaml", all the weird parts of Ocaml bleed through the reason language design. No operator overloading, nominal record typing, 3 competing standard libraries (plus the all-too-small actual standard library). The list of oddities is rather long.
SML was and is a better choice. SML has structurally typed objects and first-class constructors. No named arguments, but structurally typed objects do a better job at this (like JS destructuring, but more efficient). Anonymous records are possible. A ref type rather than mutable record fields. Only one `let`. PolyML has shipped a multi-process implementation for years while Ocaml's is still in an unending beta. SuccessorML (SML 2.0) is adding some syntactic niceties along with things like module typeclasses (modules should prevent the typeclass hell of Haskell). Most importantly, SML is a standard with multiple implementations and isn't completely tied to the success of Jane Street.
Our university was big in Prolog (SWI) and Caml Light back in the day, and they still are, just with Caml Light having been replaced by OCaml.
The only reason I known a bit about SML is because I am a language geek, it is hardly known in this side of the pound.
That's why I first loved it. I liked what I knew of Haskell but was skeptical of the Monadic IO system (I've since warmed to the idea). OCaml was in a perfect sweet spot in my opinion.
Also it feels a bit less abstract in some difficult to define way - I don't think Monads really clicked for me until I was using Options in OCaml.
I'll also second the opinion that as a _language_ OCaml is more ergonomic than Rust. However, I find that Rust is more _community ergonomic_ - it's easier to find libraries and contribute to them. Related to that - the build process is just spot-on. With OCaml, I found myself tripping over obscure errors in my build process about every month or so.
For me, OCaml is a bit like the one that got away.
But I'm excited about the momentum behind the Reason project!
I have no idea, Reason is pretty rad, but I have the feeling since 3.0 it lost steam. I mean they still didn't add async/await
Although, it would be pretty cool if OCaml got some kind of do-notation (like Haskell), a generalization of async/await sugar for any monad structure...
How could anybody rate a probability of some experimental language from Sun research lab - the tiny, fast, garbage-collected, object-oriented language for embedded systems to become mainstream - before the language was renamed from Oak to Java?
.NET Native is a proprietary, Windows-only backend compiler toolchain for statically linking and tree-shaking compiled IL, used only for UWP apps on Windows 10 devices. It is this toolchain that does not support F#.
Beyond that, there are no toolchains for compiling to a single, native binary that are a shipping part of the .NET product.
We are not prioritizing .NET Native for F# at this time (from the F# team perspective), as we feel that .NET Core gives us more reach for F#.
* Object programming with F# is based on .NET objects
* Generics in F# are based on .NET generics
* Reflection-based features are based on .NET reflection
* Structs in F# are based on .NET value types
* Newer features in F# 4.5 are based on newer .NET features
* Forthcoming nullability features will be based on nullability annotations in .NET metadata
It's impossible to divorce the two, even if the target runtime environment is not necessary a .NET runtime. Those other environments inherent language design decisions made with .NET as a target runtime. The .NET runtime with .NET Core is indeed minimal, is natively supported just about everywhere, and was built with cross-platform in mind. F# is a part of this, for better or worse.
[0]: http://fable.io/
It would surely be a lot of work, but “impossible?”
I think you’re missing a couple of major tricks by not doing a native code compiler for F#:
1. Now that Moore’s Law^H^H^HBusiness Rule has run dry, we can’t continue to just pile up the abstraction layers. Some sage once said that every problem in CS can be solved by adding another layer of abstraction, but there’s one that can’t: make it faster without buying more hardware. Given how popular FP is among the quants, a field often going after microsecond latencies, I’d think this would be a constant refrain from potential customers.
2. I don’t want to ship a dotnet runtime to my customers. Just this morning, I had to update a customer accessible only via a highly restrictive VPN, where they haven’t given my server DNS access, much less unfiiltered Internet access. Everything I ship to them has to be scp’d to the server over the VPN. I really really don’t want to send each such customer hundreds of megs of dotnet runtime stuff, then be forced to work around the failure of “dotnet restore”, so I’m going right back to C++ so I can get native binaries.
Hundreds of megs might be charitable. I just did a “du” of /usr/local/share/dotnet on a workstation here and got 1.4 GB. Presumably that compresses down to mere hundreds of megs. Contrast the size of a “Hello world” binary, which I’d expect to be under 10 kB.
I want to like F# on dotnet, but you’re making it hard for me to use it in practice.
A development environment includes the .NET SDK, shared framework, and NuGet packages. So that's going to be large in size. But you should never distribute the SDK with a published application. That's pushing a development environment onto a production machine.
If you then try to get that lower by using self-contained builds, you can only get "Hello, world!" down to about 20 MB:
$ dotnet new console --language f# -n hello
$ cd hello
...add <RuntimeIdentifier>osx.10.13-x64</RuntimeIdentifier> to fsproj
$ dotnet publish --self-contained -c release
$ cd bin/release/netcoreapp2.1/osx.10.13-x64/publish
$ rm -r ?? ??-?? zh-* # nuke i18n
$ tar -cvJf ~/Desktop/hello.tar.xz .
You'll notice that I'm giving you the benefit of high compression here. The unpacked tree is 70 MB!The equivalent in C++ is 3.3 kB.
I'm not expecting miracles. As I said, I'd be happy with "only" a 3x ballooning here, roughly commensurate with the coding efficiency benefit. That's fair.
1. Cleaner syntax. F# shows that we can do away with a lot of the visual noise in OCaml. I’m no particular fan of white space scoping, but I also don’t mind it.
2. Much better thought out standard library. The OCaml standard library was clearly accreted over long periods, with no strong designer making hard choices about naming and such. The example that keeps coming back to me is “big_int” vs all the other integer data types.
I believe #2 is what the OP meant by “minimal runtime.” A minimal F# will still need a good set of data types, a string library, etc.
Continous app [1] allows for C# and F# with an IDE, interactive programming (continuous update as you modify code appearing like Lisp live development), debugging, code completion, object inspection, and it compiles on the iPad (or iPhone), no internet needed.
It pushed me to stick to learning F# now given how seamless the experience is on the iPad Pro.
[1] http://continuous.codes/Is Typescript as close you get to Ocaml world... without writing a "ml" ?
Clean or Purescript or Haskell or Rust would be the closest you can get to the OCaml world without writing the word ML.
I still call it reason, especially when I talk about it with other js developers ;)
Typescript is unrelated to OCaml in any way.
I'd say the link between TypeScript and F# is the pragmatic approach that Microsoft took. Different paradigms but with the same care for usability. They are both great language for projects.
Flow has a quite powerful type system that mimicks (and is inspired by) OCaml. Flow itself is written in Ocaml, by Facebook.
But on the other hand, C# is more like Java (with extras) than JavaScript, haha.
This trade off is good because there is no runtime overhead, only desugaring. Typescript should never become ML or anything else that Javascript is not. If you want pattern matching in Typescript you need to convince the Ecma committee to put pattern matching into Javascript first.
What I don't see is how this requires the addition of a "runtime" on top of the JS model to make it work. I don't use TypeScript, and don't know how it implements its data types, so there may be something obvious here that I'm missing.
But it could use JavaScripts own types.
But it couldn't use TypeScripts types.
A great (albeit maybe not as great as OCaml ;) alternative for web usage would be F# with .NET Core, which has become a joy to work with over the past year or so on macos.
https://github.com/rgrinberg/opium https://github.com/inhabitedtype/ocaml-webmachine https://github.com/inhabitedtype/ocaml-session https://github.com/arenadotio/pgx (there are a few other as well, not sure which one would support PostGIS) https://github.com/Leonidas-from-XIV/slacko
When in doubt head over to https://discuss.ocaml.org/ and show an example if you run into any trouble.
Ocaml's module system is definitely worth looking at especially in contrast to Haskell's typeclass approach if you want to compare both languages.
1: https://www.fun-mooc.fr/courses/course-v1:parisdiderot+56002...
Also, you and others submitted so many more great links in this discussion, so I think all of this might be useful for others.
This property alone is worthwhile to learn one, if for nothing else then to be able to apply the same succesfull patterns in other languages.
I didn't know how to write proper strongly typed code until I learnt Ocaml - I had several years of experience in C++ and knew Java, but, they really don't go out of their way to expose the patterns that allow write the best code possible. With the lens of Ocaml under my belt I could better discern the shiny patterns that were buried all that ugly dirt of multiple inheritance and such bollocks.
Which ML language should you learn? Any of them is good as the next if it's for education - a modern tooling, support and community is a nice bonus.
ML languages in production nowadays include Ocaml, F# and, to some extent given it has so much isomorphism with its kin, Scala. Scala can be considered an ML dialect, although with the weirdest syntax of them all.
Unless you are quite certain Ocaml is the exact language you want to learn, F# is a good alternative.
Short term, officially: hell no, Evan declares a sharp focus on one use-case and discourages experiments with other platforms, even server-side node.js [2].
Short term, unofficially: I heard of a compiler to Elixir [3]. Elm's stance on "native code" (see above) seems to make such projects feasible.
[1] https://discourse.elm-lang.org/t/native-code-in-0-19/826
[2] https://github.com/elm/projects/blob/master/roadmap.md#can-i...
On practical grounds, there’s ReasonML: https://reasonml.github.io
ReasonML, a dialect of Ocaml is great for web development. Especially if you use React, due to: https://reasonml.github.io/reason-react/
ReasonML & ReasonReact are both officially supported & developed by Facebook. The creator of React is also strongly behind ReasonML.
Alternatively, there’s also BuckleScript (whose compiler is shared with ReasonML), which lets you use Ocaml with its standard syntax on the web.
BuckleScript is officially supported & developed by Bloomberg.
damn semicolons
YMMV, of course.
open Core
let () =
let n = Float.(2.0 + 3.0) in
printf "%f" nThis is an honest question, not trying to troll you.