Hacker News new | past | comments | ask | show | jobs | submit login
Introduction to Functional Programming in OCaml (fun-mooc.fr)
272 points by melling on Aug 23, 2018 | hide | past | favorite | 162 comments



Can anyone explain why OCaml seems easier for people from non-FP backgrounds than Haskell?

I tried Haskell and PureScript and didn't understand a thing.

I tried OCaml and Reason and it felt rather easy to learn.


There are two major differences between OCaml and Haskell.

First: Haskell is a pure functional language, meaning that side effects, IO, keeping state, all that must be dealt with inside the type system, which while undoubtly clean and powerful, it makes it often cumbersome to do things that should be quick and simple. OCaml, on the other hand, is pragmatic. It promotes and facilitates functional programming but it also let's you easily "drop down" (so to speak) to an imperative way to write code. You have mutable variables, imperative loops, you can perform side effects anywhere, etc. As a rule of thumb, you can write fully functional code, yet sometimes when the best way to write a certain thing is imperatively, you can do so with no hassle.

Second: Haskell is lazy, and OCaml is strict. This makes it much easier to reason about performance and makes for much more predictable code. At the same time, it has first-class support for laziness when you do need it, but you have to explicitly "opt in", so to speak. Haskell also lets you force strict evaluation, but you will find it's much easier to build laziness in a strict language than the other way around.

There are also other important differences (like typeclasses vs functors) but I feel these two are the biggest ones.


Why does laziness hinder reasoning and predictability?


Laziness disassociates the execution of a function from its call site. A classic novice mistake is to accidentally read a file after closing it -- something that can happen even if the "read" function is called before the "close" function in the code. It happens because the read function isn't actually called until its return value is used, and that can very well happen after the close call.

So you have an implicit dependency graph of evaluation that doesn't exactly match the chain of function call. You may find that some slow code gets deferred until in the middle of some time-sensitive code, for example. You could also have something blow up that's completely unrelated to the calling code, again because of the laziness.

The opposite of lazy is strict, and Haskell does let you "opt in" to strictness when you require it.


Check out Purely Functional Data Structures by Chris Okasaki: https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf


In Haskell, you have to opt-in to side-effects (monadic do-blocks).

In OCaml, you have to opt-in to lazy evaluation.


Do blocks don't allow side effects, they are just syntactic sugar that makes composing monadic operations easier.

Haskell does have escape hatches with unsafePerformIO and IORef/STRef


Yeah, but monadic composing is what make I/O and other side effects stylistic and understandable.


In (GHC) haskell you also have opt-in strictness (per module or per variable)


Yes, I think the lazy evaluation was big pain point.


Haskell is a much more complicated language than Ocaml:

- Laziness can be hard to reason about for newcomers who have really only had experience with strictness

- You have to learn a lot of concepts from category theory right off the bat, because it uses IO and monads. You need to know what a monad is, and almost all monad tutorials are notoriously bad at explaining what a monad is. You also don't know when to stop, when you've learned 'enough' category theory

- The community is full of clever tricks and idioms that aren't really necessary to write haskell code, but a beginner might think they need to know it. Examples: monad transformers, free monads, comonads, lenses, coroutines

- The type system is substantially more complex. Haskell has higher kinded polymorphism, rank-n-types, and a neverending set of extensions that a lot of haskellers use that'll keep you busy learning the rest of your life. Haskell code can also be very polymoprhic, and the type errors can be really confusing sometimes. Ocaml doesn't have these, but you can simulate the most important features: higher kinded polymorphism with functors, and rank-n-types with records

That's why Ocaml is easier to learn and use


> - Laziness can be hard to reason about for newcomers

Yes

> - You have to learn a lot of concepts from category theory right off the bat, because it uses IO and monads.

No - in particular, you don't have to understand monads to use the IO monad. You just have to understand the IO monad API. That's pretty similar to not having to understand how motors work in order to drive a car.

> - The community is full of clever tricks and idioms that aren't really necessary to write haskell code, but a beginner might think they need to know it.

Yes, and that's the major mistake people may do when starting Haskell. You don't need (and you probably can't) know everything you read about in order to be efficient in Haskell. Just use the simple stuff and live the happy life.

> - The type system is substantially more complex.

Yes, but it shouldn't be a problem. See point above, learn only what you want/need and live the happy life.

(also, Ocaml is an amazing language. It's fine if you enjoy it and don't enjoy Haskell)


If you're writing Haskell code you need to be able to understand Haskell libraries and other people's code. You definitely need to understand the type system and what monads are, unless you're main objective is to just write a toy program

The evidence is overwhelming, considering how many people want to learn and write Haskell and how many people struggle with it. If people could ignore all of this stuff they would've figured that out by now, but they can't ignore it to really be productive. I like Haskell a lot btw, just don't think it's very practical, and it's most important contributions to FP are already being adopted in other languages without the additional complexity


> You need to know what a monad is, and almost all monad tutorials are notoriously bad at explaining what a monad is.

Can you recommend good ones? I've read a few and don't feel I can say what a monad is or provide an example when asked.


See my answer to pouta


Could you point me to one of rare monad explanations?


Just read Real World Haskell and do all the exercises. After you really understand functor and applicative, and do all the exercises, monad will not be much more complicated.

After you learn the math, that is, the algebraic structure that is called a monad (after, not before) you can watch a few YouTube videos and read some tutorials, until you find the wavy-handy explanation that makes more intuitive sense to you, personally.


I don't know of any to be honest, and I would seriously just avoid all of them. Read the fantasy land spec (functions + laws and how it's implemented) instead, and ask questions on an FP channel if you're stuck or confused

I've heard 'Professor Frisbee's Mostly Adequate Guide to Functional Programming' is ok, but I'm looking at the section on monads and the monad laws aren't even mentioned. Which is a huge red flag for me, because without the laws it isn't a monad and you can get really strange behavior if you use it like that. I would avoid reading that book

People write these tutorials because they want to improve their portfolio to further their career, but they often don't even understand it yet -- a perfect example of a perverse incentive.

An example is the guy who wrote "You Don't Know Js" [1]. All of these are completely wrong statements:

- "But what I will say is that a monad is basically a value type."

- "A monad is a data structure. It's a type."

- "Actually, a monad isn't a single data type, it's really more like a related collection of data types. It's kind of an interface that's implemented differently depending on the needs of different values. Each implementation is a different type of monad."

- Says "methods" a bunch of times, there are no methods involved with monads in any way, it's FP

- His example in "Just a Monad" isn't a monad

- "Actually, the Maybe monad is a particular pairing of two other simpler monads: Just and Nothing"

- "Many implementations of a JavaScript Maybe monad include a check (usually in map(..)) to see if the value is null/undefined, and skipping the behavior if so" - that makes it not a monad, it violates the laws. Java's Optional type isn't a monad for similar reasons

- "But... that approach to Maybe is not a pure monad." - there's no pure/impure monads, it's either a monad or it isn't

- "The core spirit of a Monad says that it must be valid for all values and cannot do any inspection of the value, at all -- not even a null check. So those other implementations are cutting corners for the sake of convenience. It's not a huge deal," - It is a huge deal, a whole lot of abstractions are built on top of monads, if it doesn't satisfy the laws exactly then you'll be entering a world of pain you really wish you didn't

I stopped reading the rest but you get the point. You don't want to end up in a situation where you have to unlearn a bunch of this stuff. Btw the guy who wrote the Professor Frisbee book wrote the foreword in this book, so you can see why a lot of this stuff raises red flags for experienced FPers. My suggestion is to read fantasy land and ask questions on an FP channel

[1] https://github.com/getify/Functional-Light-JS/blob/master/ma...


For me personally, the proliferation of custom operators/syntax is a serious obstacle. When reading, I seem to need to "hear/speak" what I'm reading in my mind, and seeing a line of operators that I have no idea how to read/spell "aloud" (and thus remember, even if I manage to find their definition, which is non-trivial too), cripples my mind and renders me unable to comprehend what's going on in the code.


This was my #1 turnoff for Haskell as well. All these operators and functions, each with possibly varying precedence as well as different fixities. I was constantly having to lookup how the function was actually being called -- which of its surrounding entities were a part of the function call, and in which order did the calls take place? In addition to this complexity, the functions are often cryptic little characters (operators) that just make the readability worse. Programming languages should make our lives as developers easier, right?


Yes, this was a huge problem for me too when I tried to learn Scala.


Ding ding, we have a winner.

A lot of languages support custom operators, but some really abuse the hell out of them. Googling for <%-/\-%> is very difficult.


But you can always Hoogle for them: https://www.haskell.org/hoogle/?hoogle=%3C%24%3E


Oh!

So, first of all, I didn't know about this site, and actually it could have helped. I wish it was mentioned early enough (e.g. when first operators are introduced?) in the tutorial I was reading (Learn You Some H.? Not sure, don't remember now.)

Secondly however, I see it still doesn't mention how to spell the operator. Though I suppose in this particular case "fmap operator" could be acceptable?...

edit: Eh: see for example '>>=' and '>>'. Based on the docs, I could only try to call them both "compose", but they need some differentiation in my mind...


Yeah, the first one is called `bind`. The second one is a variety of `bind`. But you can just lookup the symbol in Hoogle and it will give you the definition.

You can also lookup a type signature and Hoogle will give you all functions for that type signature. For example, there is only one total function `(a -> b) -> [a] -> [b]` (map) and if you search that Hoogle will show you map, accordingly: https://www.haskell.org/hoogle/?hoogle=%28a+-%3E+b%29+-%3E+%...

Honestly Hoogle for Haskell is better than Google for other languages for finding things.

EDIT: Oh, you can also click to go to the operator docs. For the case of <$>, the docs would tell you that it's an fmap synonym.


Haskell forces you to manage effects explicitly, even for e.g. input/output. In a production system this is probably a good idea (most of your functions shouldn't be doing I/O and you probably do want to flag up a function that is), but when you're just trying to get started with "hello world" it's a confusing extra complication.

If that was your problem, it might be easiest to start by doing things in the REPL (GHCi) where you don't need to be doing I/O, and only start writing standalone Haskell programs once you're a bit more comfortable with the language. But I'm just guessing - maybe you found some other aspect to be a barrier?


I had the feeling Haskell would use much more FP jargon than OCaml, I think.

People where talking about profunctor optics, monads and lenses, stuff I never heard of.


Those are useful general-purpose libraries. Treat them like any other library with its own specialized terminology - and, like any other library, don't use them until you need them.


I think a big problem is that it's hard to slowly develop "taste" in Haskell. That is, it's hard to navigate the path from not knowing what you do and don't need to use to accomplish your task, to being able to tastefully choose the right tools. Like you say, things like lenses are just useful libraries that you may or may not need, but how do you know? People on message boards and blogs may suggest that they are the right way to solve your problem, and you have to grok a bunch of stuff to determine whether or not you agree.

I find this harder in Haskell than other languages, because I find it harder to progress slowly. In most languages, step one for a beginner is to just hack something together, maybe even using direct for or while loops, switch statements, and the like. Then you can go back and figure out what the language gives you to express what you've done in a better way. Then you can iterate on that basic process, moving up the levels of abstraction, often finding at various points that you didn't need to write any of the code you wrote because a library exists that does the same thing if you call it in the right way. By the time you're reading about the library, you understand the contours of the problem it solves, because you've already done a worse job of solving those problems yourself. I've always had trouble injecting myself into the right point of this step-wise procedure in Haskell, and instead feeling like I need to do a bunch of research on the right ways to do things in order to make any forward progress.


I think the issue is that the frameworks in Haskell expose the generic abstractions they're built on, whereas in another language a similar framework would just offer opaque magic. E.g. when writing a web endpoint you can see that you're returning something that uses a monad transformer and you can easily dive into the details of what that means and what the framework functions that manipulate that are actually doing: in the long run you will eventually want to do that, but in the short run "the framework will call your function with these parameters, by magic, and customizing that behaviour requires you to change things in the framework's internals" can actually be easier to get started with, since it tells you clearly which parts you should be messing with and which you shouldn't.

I don't have a good answer, because I wouldn't want to stop building Haskell frameworks that way. But I do agree it's a problem.


Sounds reasonable.

The way people talk about them often feels to me like they are language constructs.


They're not, but they're general-purpose enough that you end up using them in a similar way. When you have higher-kinded types it becomes possible to write very general libraries that are applicable to a lot of different problems. This is great because it means you can reuse the same libraries you're used to in a very different domain, but it can make it harder to learn them because they're not about anything specific.


I think there's definitely a haskel trend to prefer "accurate" nomenclature vs merely "serviceable correct". That is to prefer "joint rod and spherical cap digging implement" vs "shovel".


Did you try OCaml and Reason after your attempts to learn Haskell? That might have something to do with it. Sometimes we don't get the idea the first time we are exposed to it and we need time to let it sink in. It's when we are exposed to the same ideas a few times in different formats that it starts to trigger our tendency to notice patterns.

I have observed a similar effect that it seems like plenty of people come from an imperative language to OCaml and stay in OCaml longer than say, Haskell. Although I'm not sure why that is but maybe they are much like you and tried Haskell first?


Yes, I did try it after Haskell.

I had the impression the FP hype started with Haskell and so I tried it, alter people started talking about OCaml, so I gave FP another try and liked it.


I did as well. I tried Haskell on my own in the aughts before giving up. I had some fond exposure to OCaml and SML but never got into it until I heard the Jane Street talks, heard about MirageOS, and decided to take the OCaml course in 2016.

I've since gone back to Haskell and am finally enjoying it... but I credit OCaml with getting me to a place where I could enjoy Haskell the second time around.


I personally found the syntax in the ML series languages to be clearer when learning. I found Standard ML/NJ to be even easier (and potentially nicer) than OCaml for what it's worth.

I think it comes down to visual cues. Haskell eschews syntactic sugar and I personally find it hard to read the structure of expression. I found ML to be more explicit.

That and the community around Haskell really loves... clever... constructions. And its type system is more expressive but also complex from a mental model POV.


Seconding this. I got discouraged trying Haskell. Came back and tried it with Racket and things made more sense. I certainly wouldn't give Haskell as someone's first functional language.


I have fond recollections of learning to program in Caml (this was in 1997). Without ever being “indoctrinated” to FP (I only recently made the connection to FP), we learned recursion, list manipulation, pattern-matching and currying before loops. Tail-recursion was the standard way to write a function. I don’t think teaching the same concept to first year students would be as easy in Haskell (although I only know the language from LYAH)


[ed: where I say ml, read sml - standard meta language]

One of the reasons I'm interested in fb's reasonml dialect of ocaml is that I stumbled a bit going from plan ml (meta-language) to ocaml. That said, I think ocaml too is less complex than haskell. But more so ml.


One word, laziness.


For everyone interested in learning OCaml, there's a very active Discord community where you can ask questions: https://discord.gg/ZBgYuvR

Join and say "hi"! :)


Does anybody else think functional programming is just one end of the either/or fallacy? Maybe a trap for contemplative people?

The ultimate goal of software is to build something useful. The "functional programming tutorial:real world uses" and "claims of superiority:adoption" ratios are suspiciously high.


This is true to some extent (IMO Elm and Haskell) but I think at least being exposed to one functional language will make anyone a better developer in all languages.

I started programming in Clojure, Clojurescript, and now messing around with OCaml. The primary language I use at work is Ruby.

The aspect of FP that really helped me even be a better Ruby developer was just having way less shared state. When you have less shared state, and small functions doing one thing with as little side effects as possible it really makes code cleaner and it makes your software behave in much more predictable ways.

I know what some are saying "Well that seems like what you should be doing anyway..." That is true but at least working with a FP language really drives this home and for me did more for code quality improvement than anything else. In fact now when I look at most Ruby code even in big high quality projects I am like why??? Ruby gives you so many ways to do things without shared state (blocks) yet so many choose to set instance variables all over, or store stuff in variables in memory.

I still am not sold on strong static typing such as in Haskell, and yes I get the opinion of what you said about that community. I am not sure though if it is because I am bad at it, or it truly takes more work than it saves you in the future. I just find with FP as in Clojure and OCaml it gives me a lot of gain without ever getting in my way. So it is worth trying, and even if you keep working in a large imperative language, FP experience will help you not fall into the holes of large shared state.


> Does anybody else think functional programming is just one end of the either/or fallacy?

I think viewing this as a fallacy is a bit of a straw man. There are very few people who believe in a "Right Way (TM)" to write programs (although those people are probably over-represented in the comments section of online news posts about functional programming).

> Maybe a trap for contemplative people?

FP is hardly unique in this regard. Were you around in the 1990s? Recall that the OOP crowd got pretty philosophical there for a while, with elaborate treatises on software organized around some obscure book about architecture. ;-)

> The ultimate goal of software is to build something useful.

It's worth noting that the ultimate goal of functional programming (as a research field) goes beyond building software; (typed) lambda calculi are an entire alternative model for studying computation. The science of computation has many applications beyond software development.


I think you're right that if FP is a trap at one end of the fallacy, pure OOP exists at the other.

Interesting point about software having uses outside of programming a machine to do tasks. I can see an appeal there.


> I think you're right that if FP is a trap at one end of the fallacy, pure OOP exists at the other.

I disagree; what spectrum are those on opposite ends of? Encapsulation, polymorphism, and inheritance are entirely compatible with FP, and immutability is entirely compatible with OOP. Functions and objects are equivalent. Most mainstream OO culture is centred around procedural programming, but it's the procedural parts that oppose a functional style, not the OO parts.


> I disagree; what spectrum are those on opposite ends of?

I also am not entirely sold on funfunfun's characterization, but if you think of this in terms of cultural hangups that cause excesses rather than concrete technical contributions then it makes some sense.

The excesses of OOP culture are distinctly different from the excesses of Functional culture.

OOP in excess looks like software architecture books with quotes from Alexander and FLW, programming as artform, etc.

Functional in excess looks like really bad descriptions of category theory promulgated by writers who couldn't tell you what group theory is good for.

So if we want to characterize these ways of programming in terms of what harmful excess looks like, then they are on sort of opposite sides of a spectrum. Where one side considers programming pure art and the other pure logic.

I'm still not sold that this is a good model of reality. But if you focus on excesses rather than useful insights, I can see what funfunfun is saying. I think.


OCaml isn't very extreme in its approach. It's a functional language, but it also allows side-effects and has object with mutable state, for example. It's most certainly a language that is being used mainly to build things. See https://ocaml.org/learn/companies.html and https://ocaml.org/learn/success.html for examples.


I've been primarily a professional Clojure developer for several years, that's how I earn my living, and thus I have used the language in many contexts. In the beginning I was in love with it, in hindsight at least part of this love was the thrill of doing something new. But my appreciation for that style of programming has gradually declined over the last 5 years.

FP is great for many little things you might have to do. But for larger architectural considerations, I still find notable advantages to creating custom classes that have their own public API, private internal implementation, and that manage their state internally. In the absence of this, you have lots of functions that are basically sitting alone with their pure inputs and outputs, and to manage state requires more effort, not less, in a lot of situations. Each of these functions has to receive the thing they are acting on, and a separate group of functions manages the actual mutation, acting as "controllers" between these more pure functions and the actual stored state. The result is a less elegant program structure sometimes.

FP enthusiasts like to say that "it's better for many functions to operate on common data structures than it is to have many custom data structures with their own functions." The problem in my experience is that often, these pure functions are only serving one purpose geared for a particular data layout, and thus they might as well be coupled to it; the lack of a backbone in larger FP architectures can be frustrating. In Clojure, you have maps, and all maps behave the same. Great. But not all maps are actually the same. Each map ultimately has its own structure, and these functions that operate on a particular map are really operating on a particular structure a lot of the time. So you end up with increased verbosity and more difficult-to-follow code structure than if you just combined the data and its functions in one place: a class. The record-protocol idea attempts to alleviate this, but I don't feel it really gets to the heart of the issue.

I think OO and FP each solve problems in equally meaningful ways and different tasks are better suited to one or the other. I particularly like languages that don't force you into a particular model. Java and Clojure are quite opinionated (in opposite ways) and thus often inflexible for certain tasks. My favorite language for blending these techniques has become C++ but I don't get to use it as much. It offers true FP-style programming with constructs like std::function. I wish Java had gone as far as C++11 did; the Java lambdas and the requirement that they can only be type defined using a static interface is not really helping to adopt the paradigm.


> FP is great for many little things you might have to do. But for larger architectural considerations, I still find notable advantages to creating custom classes that have their own public API, private internal implementation, and that manage their state internally.

In OCaml, you usually do that with modules. For instance, you can easily write mutable or immutable datatypes that hide their internal representation.

> My favorite language for blending these techniques has become C++

I also like programming languages that embrace several paradigms. The problem with C++ is that it's a very complex language. Compared to C++, OCaml is a piece of cake.


^ what yodsanklai said ^

Ocaml has declarative OO programming via it's module system. Typeclasses and Ocaml modules have equivalent expressive power, so you'd achieve that with typeclasses in Haskell. But Ocaml's type system is much simpler and more explicit, which makes it much easier to learn and use


I'd disagree (though it's certainly not the tool for every job). I think it has more to do with the old line that FP makes "the hard things easy but the easy things hard". It's a really different way of thinking about things that is intuitive if you're used to the imperative way of doing things.


> Does anybody else think functional programming is just one end of the either/or fallacy? Maybe a trap for contemplative people?

> The ultimate goal of software is to build something useful. The "functional programming tutorial:real world uses" and "claims of superiority:adoption" ratios are suspiciously high.

Yes and no, what they're really getting at is declarative vs imperative programming and how declarative programming makes managing state and reasoning about code much simpler. In imperative code you often have to step through mentally or through a debugger to really understand what's going on. It also really simplifies concurrent programming (ie map-reduce).

You can have it both ways -- declarative OO programming exists with Ocaml's module system. You can even write declarative OO programming in Java, using 'static' classes (or non-static but only used to configure so it's essentially immutable), 'final' everything, and immutable data structures


Yes, there is only Curry-Howard and all PLs are just projections (to greater and lesser degrees).

Referential transparency, mutation, non-termination, coinduction, memory pointers, linear types, coroutines, continuations, blah blah blah. All of these things exist, and more.

Most PLs are biased in one way or another, many don't even let you reason formally about those things (or allow you to reason informally).

But at least if you're a working programmer, especially if you work to map an existing human domain to software, there's always the fixed point of Curry-Howard to hang on to.


Exclusively functional? Yeah, kinda. But I do like it when languages allow me to use functional paradigms internally, so that when a problem is really suited for it I have that option.


Turns out Haskell is great for “building something useful” though.

At least that’s been my experience in my years of writing professional, money-making software in it.


I started this course but really struggled with their strong accents (although subtitles are available)

Guess I know how the rest of the world feels now watching American tutorials.


Most other English-speaking people in the world deal with different accents reasonably often in media and their lives, the American accent most of all. I think it's more that it's easy for American's to live in a bubble, because the country is so large - it's sometimes odd to see American media putting subtitles on strongly accented but otherwise perfectly intelligible english speakers, for instance.


Beyond the 2-minute intro video, the audio became very faint, with background noise like a fan humming. Made it tiring to listen to. (Does it get better later?)


If you’re on a Mac, it might be CoreAudio acting up.

Try sudo kill-ing coreaudiod

(disclaimer: I haven’t seen the video in question, but I had a similar problem with online videos in general)


I don't see other videos other than the intro. It says the course doesn't start until next month.



"How’s F# adoption?"

Based on inferences it has a small, enthusiastic and talented userbase and has still language core developers bankrolled by Microsoft.

There's been some worried discussion whether Microsoft wants to continue investing in it or not, e.g.:

https://www.reddit.com/r/fsharp/comments/91gg6j/is_microsoft...

Personally I hope they would continue the investment.


Obviously it's not the first language to implement a "pipe" operator, but apparently F# was the original inspiraton for the %>% pipe operator in R. Not only was the idea of "piping" itself a small revolution in data analysis/science coding, but it was the gateway to introducing functional programming and metaprogramming principles to a wide audience of non-computer-scientist users. So its legacy will live on, even if the language does not.

For me, at least, I've had negative experiences with Mono-based applications on non-Windows platforms (e.g. Keepass), so that is scaring me off from wanting to build anything on .NET.


Have you tried F# on .NET Core? People seem to be quite happy with F# on .NET Core compared with Mono, at least for server/web/cloud programming.

Data science-y stuff is our next target, starting with finishing out our REPL support for .NET Core. It's not fully functional (turns out it's a ton of work!), but when completed it'll have support for ingesting packages in a REPL session, and it'll work with libraries such as ML.NET.


I really like a lot of F#, but it is really difficult for those of us with limited .NET experience (Python, R...etc experience here). There are several F# books, but it's all a bit above me. If you are an F# evangelist, please consider spreading that idea around. Maybe an updated tryFsharp.org would help. Not just REPL snippets either but how to put things together.

I appreciate everything the open source community does btw. It is just a little frustrating that there is a really cool language and ecosystem that I'm only making glacial progress in.


"F# for scientists" by Jon Harrop is awesome especially if one comes from a less computer sciency background. It shows exactly how to use F# effectively in a numerical context.


The guy is a god. I've been meaning to check it out.


F# is available in Azure Notebooks so I guess it’s fully supported


Microsoft is throwing everything on Azure these days, I won’t be surpised if a significant proportion of these services are discontinued in the next years.


Why should they when it gets used and makes them money?


A usable industrial strength tool needs more than just the compiler and a repl.

The main benefit of an industrial language is the entire toolchain including IDE with code higlighting, intellisense capabilities, debugging capabilities, etc. To provide these for F# in Visual Studio requires continuous investment.

Hence, given the not-entirely-committed feel MS is emanating just now for it, if they don't feel supporting F# as a first class citizen on visual studio is worth the investment, they might orphan it to to open source developers. Who probably would hold good care of the core facilities, but would probably lack resources and interest to provide an entire industrial strength stack. I do hope this is not the scenario, and Microsoft will continue investing in the language as a first class citizen on visual studio.


You can check out some of the investments we've been making for F# holistically here: https://blogs.msdn.microsoft.com/dotnet/2018/08/14/announcin...

(lots of language stuff at the beginning, but there's a tools and "what we're thinking of next" section afterwards)


Thinking of next, as usual is only interesting for the usual type provider demos, not for the working programmer using C# and VB.NET across EF, Forms, WPF, UWP, ASP.NET MVC, IoT Core, HoloLens.


This. As an industrial programmer: F# was awesome 10 years ago, I don't really crave for new language features. I want an industrial strength tooling and ecosystem to support this awesome language, not new language features.

To be painfully blunt: The language is really nice as it is. I would prefer it would expand on the bolted-on batteries included utilities rather than new contrived ways of code golfing.

What is critical from industrial point of view that the fundamentals are now and "forever" rock solid. Not how many new language features it will gain.

See C for reference. Nobody uses C because it gets new ways to write shorter code. People choose C for stability[0], not because it's horrible language or because it's a beautiful language.

F# would be fantastical, if it would ossify like C. Then I could write it for the rest of my programming career.

[0] Yes, C moves forward, but with a geological pace


I think your definition of "working programmer" is a lot more specific than you're implying here. There are numerous working programmers using F# successfully today, in a broad number of scenarios. Machine Learning is our next one to tackle.


I don't need F# for ML.NET and still get to use it on the above scenarios where F# gets a no entry to play allowance.


I don't know about general F# adoption, but I've used it for personal projects and I quite like it. I'm trying to convince work to let us use it in production.


Great to hear that you're working to convince people to use it in the workplace. Not sure what your approach is, but a few things have worked for people very well:

* F# for unit testing

* F# + Giraffe or Saturn deployed to Docker containers on .NET Core (people tend to love the succinct routing and that it all runs on ASP.NET Core in Docker)

* F# for internal tools to ingest and manipulate data, then put it into another place in a much more sane format

* F# with FAKE for a right proper build script

* F# with Azure Functions to perform some scheduled task or something like that (it also helps that Functions is dirt cheap)

Good luck!


If only my workplace used Azure for some stuff. We're moving to serverless architecture for a lot of our apps, but it's all on AWS so no F# :(. The other .NET guy at my company (wpf) and I have been singing the praises of Azure and using .NET core for future developments. I think that they'll eventually throw us a bone since they don't want to be dependent on a single cloud provider.

However, I have messed around with data manipulation in F# for sports betting, and it's been exceptionally pleasant.

Love the work you guys are doing on the F# team.


F# actually rusn _very_ well on AWS. There is some official scaffolding tooling you can use[0], and performance with .NET Core is more than sufficient for what your business likely needs[1]. Love this quote: "Both C# and F# on .Net Core 2.0 exceeds all expectations and outperforms all other runtimes in average duration".

Thanks for the compliment! And I hope that it all goes well with you.

[0]: https://aws.amazon.com/blogs/developer/f-tooling-support-for...

[1]: https://read.acloud.guru/comparing-aws-lambda-performance-of...


Thanks for the information! I'll try to let you know if we ever get something going.


My company runs F# + .NET Core on AWS Lamba (almost our entire backend infrastructure). We've been very happy with it.


I'm in the same boat, coming from Python. I like it a lot -- it lets me write things that are hard to express in Python. (Sum types and exhaustive pattern matching in particular.) My Python had been moving in this direction anyway -- less OO, more procedural, more pure functions, limited mutation.


Exactly. We're doing the same thing with my C# project at work. It's becoming more "functional" as we refactor and fix bugs. The project has been much easier to work with.


Sorry to hijack the thread:

I recently was trying to decide which language to pick up next: Lisp, OCaml, F# or Haskell (I know a bit of Lisp and Haskell already, as well as some Standard ML).

It came down to two: OCaml and F#. The former has poor support in Windows (work machine), and the latter has less poor support in Linux (home machine). So I decided I'll probably go with F#. I've been told the syntax is quite similar, so how difficult is it to translate an F# program to OCaml. Are all the patterns the same that one can do a more or less 1:1 translation while still being canonical?


Going from Ocaml to F# is trivial, most of the time it is only a matter of adjusting the indentation and getting the correct name from the std. Going from F# to Ocaml tend to be harder since F# has a number of functionalities that are often used and do not exist in Ocaml (such as parallelism, sequences, active pattern, list comprehension, type providers, etc and a much bigger std). As a user of F# on linux, the experience is good (better than Ocaml on linux) and getting better every year (some library are still windows only but it is changing).


>Going from F# to Ocaml tend to be harder since F# has a number of functionalities that are often used and do not exist in Ocaml (such as parallelism, sequences, active pattern, list comprehension, type providers, etc and a much bigger std)

The opposite is also true, F# does not have ppx, OCaml's object system, GADTs, polymorphic variants, functors, first class modules, extendable variants.


Better than OCaml on Linux or Ocaml on Windows? If it's better than OCaml on Linux, that would be impressive.


F#'s object model is very different from OCaml's. F# is basically the same as C# when it comes to objects, but OCaml has some sense of structural subtyping that F# lacks. On top of that, OCaml has a very powerful module system, whereas F# has a pretty standard one.

On the other hand, F# has computation expressions (essentially extensible syntax sugar for certain kinds of operations), as well some nice extensions to the pattern match system.

That's not to say one is exactly better than the other, they just focus on doing different things.


Have you tried F# on .NET Core? There are plenty of people using it exclusively on Linux (both to develop and as a deployment target).


I use F# every time I have to write a parser for the sole reason of FParsec, which is a godsend and a joy to work with


This is a brief history of OCaml and ML family

https://blog.baturin.org/images/fp_genealogy.png


It is the stepchild of .NET.

There are still a few deployment scenarios where only C#, VB.NET, C++, JavaScript get to play and F# gets no entry.

A few F# features still don't work on .NET Core, like REPL and type providers.

Speaking of which, type providers is the king of F# demos, instead of discussing how and if ever .NET Native devs will care about F#.


Type Providers have worked in .NET Core since April.

Edit: https://twitter.com/dsyme/status/981799285925842945?s=20


Thanks for the correction. I lost motivation to keep following up F# tools being also ran for C# and VB.NET.


F# is not a derivative of OCAML, though it was that way in the very very first version (pre-1.0). Since then, it has diverged a lot, though it does have the same core syntax and "feel", and even has a flag (--mlcompatility) that allows you to compile a subset of OCAML programs with F#.


They all belong in a continuum of ML languages, starting from (I think) SML.


No, I think SML was an attempt to standardize the various dialects of ML (which was the original) that had been invented. OCaml was a version of Caml with Object-Oriented additions. (I remember playing with Caml Light many years ago).


A bit offtopic but: has anyone used SML (https://www.smlnj.org/) for anything serious?

I fell in love with this language in University long ago (in the 90s), but I have never seen anyone use it in the wild.


Mathworks hires SML programmers for their various products that detect runtime errors and proof assistants for C/C++ programs


I tried OCaml first and then SML/NJ and I found SML/NJ to be a nicer language. But OCaml seems to have a lot more momentum behind its use.


I'm sure that a big part of OpenModelica compiler is in SML.


ur/web is written in sml: http://www.impredicative.com/ur/


Thank you


There is a work-in-progress second edition of "Real World OCaml" book [1], which has many small but vital updates corresponding to the modern state of OCaml and its infrastructure. Moreover, I recommend checking the Lwt [2] from the beginning for working with multithreading. OCaml Ctypes [3] library for creating FFI stubs without a single line of C and Cstruct [4] for working with C structures. If you want to interact with some Python code or script your OCaml program with Python - you can use Pyml [5] library. OCaml universe also has a good library for numbers crunching and scientific computing (including primitive Machine Learning) - Owl [6]. For writing OCaml instead of JavaScript, it is possible to use BuckleScript [7]. And if you are starting a new project in OCaml - I recommend using the most modern buildsystem - dune [8]. It is very simple to use and with a less overhead than others. I found also Angrstrom [9] is very useful for implementing binary and text format parsers.

Utop [10] and ocaml-jupyter [11] are the best choice for experimenting, browsing the API and testing some small things.

[1] https://dev.realworldocaml.org/toc.html

[2] https://ocsigen.org/lwt/manual/

[3] https://github.com/ocamllabs/ocaml-ctypes

[4] https://github.com/mirage/ocaml-cstruct

[5] https://github.com/thierry-martinez/pyml

[6] https://github.com/owlbarn/owl

[7] https://bucklescript.github.io/

[8] https://dune.readthedocs.io/en/latest/quick-start.html

[9] https://github.com/inhabitedtype/angstrom

[10] http://github.com/ocaml-community/utop

[11] https://github.com/akabe/ocaml-jupyter


Speaking of problems, in my opinions the three biggest are:

- Lack of automatic multicore scheduling, this is going to be solved with OCaml multicore project [1]

- Lack of updated GUI libraries. There is LablGTK [2], but it stuck to GTK+ 2 version. The main developer started [3] to work on GTK+ 3 version support, but it is still at the very beginning.

- Bad Windows platform support [4] (grep for "Windows" word at this page) and [5]. With upcoming opam-2.0 [6] release the support will be slightly better though.

[1] https://github.com/ocamllabs/ocaml-multicore

[2] https://github.com/garrigue/lablgtk

[3] https://github.com/garrigue/lablgtk/issues/2

[4] https://caml.inria.fr/mantis/roadmap_page.php

[5] https://github.com/ocaml/opam/issues?utf8=%E2%9C%93&q=is%3Ai...

[6] http://opam.ocaml.org/blog/opam-2-0-0-repo-upgrade-roadmap/


We use OCaml on windows everyday and have no problems with it. Since the support of foreign encoding (recent) there is no major issues with OCaml. The support is not perfect, but you can't say that it's bad.


Careful before using LWT, it produces unhelpful stacktraces that just show the thread starting point instead of the actual running code. I have some production stacktraces where I have to guess where the error lie while the customer's backup are in danger.


This probably means your code is wrong. You should not raise and catch exceptions normally in Lwt promises. You should use `Lwt.fail` and `Lwt.catch`. This is described rather precisely in the documentation: https://ocsigen.org/lwt/3.2.1/api/Lwt

Another popular solution in the OCaml community is to stop using exceptions and use Result instead: https://ocsigen.org/lwt/3.2.1/api/Lwt_result


Lots of libraries we depend on throw exceptions, e.g. yojson, postgresql, or even just the stdlib (`Invalid_argument`, anyone?).

Because the exceptions aren't statically shown at each usage point, it's hard to know what failure modes you should be watching for.


it's not my code, it's there, I can only send PR and hope.


You recommend LWT, but the book you recommended teaches Async instead. The split between with libraries to use (e.g. stdlib vs Base) has been frustrating as I’ve been learning and needing to look up documentation.


If you are following the Real world OCaml book but want to see the exercises in LWT, you can refer to: https://github.com/dkim/rwo-lwt


I use Core/Base library but rarely use Async. In my opinion and experience (though a short one), Lwt has more features and better maintained by the community.


This is a fun course. I completed it the last time it was ran and had a blast. I was proficient enough by the end to start writing small to medium programs and libraries in OCaml.


While this may no longer apply, could you give an idea of the strictness of the schedule? I am very interested in this, but I'm going to miss the first two weeks, as I'll be on leave. If it's simply a case of playing catch up, then that's fine, but if assessments, etc. are rigidly set on dates, then that would be a deal breaker for me.


As I recall you can complete the course at your own pace. They have an online checker you submit your exercises to.


FWIW the archives of the previous course are available.


I am currently doing some interventions in some Ocaml code written by Big Co. The world is completely different between you writing your program in your corner, and stumbling in a codebase with a serious history and a task to do on it efficiently.

It's not going quickly nor easily, and there is no real help from Jetbrains IDE.


it should at least offer things like "show-type-of-expression-at-current-cursor-position"


It does. Install caml-mode or tuared-mode in emacs. Add -annot to ocamlc compilation flags, and type C-c C-t et voilà.


It doesn't, it colors some keywords, it tries to follow symbols, but doesn't know the difference between 'let rec' and 'let', so it's tricky.


Maybe JetBrain doesn't, but lot's of editor do, thanks to merlin, including vscode.


Thanks, I'll download it, but it's really disruptive to switch IDE. (I do a lot of langages at the same time hence the jetbrains suscription)

edit: it's a nightmare of dependency hell to install merlin, I'm giving up for now.


What package manager? `opam install merlin` should just work.

OCaml has a relatively immature ecosystem, but merlin is a great tool.


It doesn't just work for me, no detailed error message I'm 3 or 4 levels down (vscode->plugin->homebrew->opam->jbuilder-> doesn't work).

https://gist.github.com/nraynaud/deeacbb67c88646fd6754edba6e...

Sorry, I'm a bit abrasive, but I spend a lot of time with crappy tooling of all kind, sometimes I'm envious of monoproject people (and then I remember that actually I don't do well in monotony).


I think `opam` failed to find `jbuilder` on the `$PATH`, even though (presumably) `opam` has built it and installed it in it's own `bin/` directory. Try running `eval $(opam config env)` to update the `$PATH` and trying the commands again.


It looks like out output some logfiles. Anything in them? Apologies, at any rate, for being wrong about it just working.


Why are you not using emacs? Or why did you accept the job if you don't want to use emacs?


OCaml and Reason are beautiful languages. I actually applied to Jane Street hoping for a chance to use them more, but they weren’t interested in my resume. Is there a list of OCaml/Haskell/etc companies out there for us functional programming enthusiasts?


Dark is written in OCaml (and Elm, which is a similar functional language) and we're hiring: https://darklang.com/careers/


Wait...hiring to sell a Lang? I'm curious.


The business model is fairly easy though: sell infra. It's a lot to build, so we need a good team. We're currently 5, hiring 3 more engineers atm.


The Tezos project uses OCaml to build the core network and protocol features (but not the smart contracts). Companies are starting to build products based around Tezos and OCaml knowledge will be valuable for some aspects of that. See https://gitlab.com/tezos/tezos for the code.



As an aside, as someone who primarily uses imperative languages, I’ve found the proliferation of support for functional paradigms in Python and C++ (Fold expressions, reduce, transform, map, etc) has changed how I write code immensely.

I’m likely to try this out.


your opinion is super valuable, do you think they make your code shorter, cleaner, more modular, safer ? what do you miss from imperative programming ? or do you consider you would have changed the way you code if you knew about fp idioms long before ?


1: Cleaner and more concise. Perhaps safer, as the less code there is going to performing a task, the fewer places I can make a mistake. More importantly, it directs me to think about my problem from a higher level of abstraction.

2: I do mix both paradigms, so I’m not stuck without imperative features. That being said, there are times where I feel like my attempts to move a concept into FP forces me to make some less than ideal choices to fit it into the paradigm. If those are in inner loops, I forgo functional programming to do precisely what I need. (For example, managing exceptional cases or heterogeneous actions can be awkward.)

3: I would have used them more. I’ve always been a fan of comprehensions and map c/o Python, but my code would have been more efficient and concise had I started earlier. The additions of cppitertools, range-v3, <algorithm> and <functional> make functional programming both easy and efficient in C++ in ways it was not prior to C++1[147]. I think Python made fp accessible by putting it in an imperative language which is concise and readable.


about 2, I remember some old lisp book (Queinnec L.I.S.P) said that if mutable state is entirely contained and invisible, you can forget about purity.

It's cool that cpp is 'flattening' through fp idioms, you can avoid its complexity without leaving the country entirely.


E.g. a pure function can work internally by mutating some local variables. Locally constructed new objects such as conses can be mutated before being returned to the caller. Blackbox testing cannot tell.


My 2 cents: I love functional programming, but sometimes imperative code is the right solution for something, like quicksort.

I'm ok with imperative code as long as the mutable state doesn't 'leak out' into the rest of the code. Quicksort is an example of that -- it's impure in it's implementation but essentially pure to the end user, because you can call it any number of times with the same input and it'll always return the same output

Or if it's some looping construct, recursion might be ok but if it isn't readable or you don't get tail-call optimization, then a for or while loop makes more sense. I do prefer map/filter/reduce/forEach or recursion, I think it's more readable and it avoids the indexing class of errors


Is it possible to enforce purity for parts of an OCaml program? Or is there always a way around? (Not saying this is bad, because for instance caching functionality is non-pure but still maintains the external quality of purity).


There is work being done to bring an algebraic effects system to OCaml, but it's slow going. I think because the people pushing it have a bunch of other things on their plates too. But it would be super nice to have!


Best part of this is the very pragmatic set of problems. I loved the meijer haskell mooc too, a lot, but it's more about mind bending rather than more day to day programs.



OCaml is a very powerful language. I'm still discovering new features/patterns everyday. But coming from a background with C/Javascript, the syntax is definitely hard to understand. For this particular problem, I think ReasonML has done a very good job of introducing OCaml platform to a wider audience.

Shamelessly plug: I'm working sketch.sh [1] as a learning project for ReasonML. It's a interactive playground (like IPython/Jupyter) for OCaml and ReasonML. It's provide inline types and evaluated values. Give it a try if you're learning OCaml/ReasonML.

[1]: https://sketch.sh


> But coming from a background with C/Javascript, the syntax is definitely hard to understand.

I work with Haskell fairly regularly, and have experience with a few other languages (Python, Racket, C/C++, Java, etc.), but I definitely agree with this sentiment. I am not a fan of OCaml's syntax at all.

I haven't had a chance to check out Reason yet though, so maybe I'll spend some time playing with that soon!


I don't think its syntax is that bad. A bit daunting at first, but it isn't like you need to learn a ton to understand it, so once you have the basics it is pretty readable.


I don't get it. I work day to day with Algol-syntax languages like JavaScript and Java, but have dabbled in ML languages like Elm and Haskell. One of the things I really like about those languages is the syntax -- succinct and clear. What takes time and is hard for me is grasping the semantics and patterns.


OCaml's syntax is way more verbose and noisy than Haskell's or Elm's. It tends to have longer keywords, more sigils, … and some of the defaults are inconvenient (non-recursive lets)

https://wiki.haskell.org/OCaml has some trivial examples


I find it pretty clear in simple cases but ambiguities and associativity rules can make interpreting some code a real pain.


As a contrasting opinion I started reading the Ocaml book about something real world and I felt the syntax finally something fresh, beatiful and clean. But I also suffer from having to use scala everyday at work.


As a big Ocaml fan, the syntax is one of my least favourite aspects of the language.

Two things that I find particularly annoying are constructors (which don't have the same syntax as funciton calls) and the multitude of shift-reduce ambiguities that don't do the thing that you want. For example, in the following code the W gets parsed as part of the inner match:

    match foo with
      | X -> match bar with
               | Y -> 1
               | Z -> 2
      | W -> 3
A lot of this could be remedied by having more expression terminators. ReasonML uses C-like curly braces but even a simple "end" token to close the match expressoin (similar to what Lua does) would already be enough.


This tripped me up when I was first exploring OCaml. FWIW i've taken to wrapping the nested matches with parenthesis or a begin/end

    match foo with
      | X -> (match bar with
               | Y -> 1
               | Z -> 2)
      | W -> 3

    match foo with
      | X -> begin match bar with
               | Y -> 1
               | Z -> 2
             end
      | W -> 3


The indentation sensitive syntax of F# was the solution to me, I would love to see it being integrated into OCaml.


Ohh interesting. Didn't get that far yet. But good to know. Is there somekind of place listing these gotchas with the syntax? Seems something good to be aware.


Check out the point "comparison to ocaml" in the reasonml docs


"This course will be held in English."

No offence intended, but English, my ass!

Although quite proficient, English is still a second language to me and this accent makes it quite unintelligible. I hope everything will be available in written form as well.


[flagged]


What are you talking about... “violence supporting”?!


He's probably referring to these posts on Twitter: https://archive.is/BtDaA




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: