Live data from Hacker News

OCaml as my primary language

xvw.lol

91–100 of 296 posts

Re: OCaml as my primary language

#91

Earlier quoted context omitted.

The RESF is not a conspiracy theory, its a known thing. Especially on HN: https://news.ycombinator.com/item?id=14178950

It's real, and as someone who loves rust, it's embarrassing, and difficult to avoid. The OSS embedded rust users in particular are nuts.

Really appreciate a fairminded Rust person chiming in. It's a disservice to the language (which is cool!), and it makes the community look bad.

Rust might gain some adoption among people who are new to high performance software and see a narrative that its the only game in town, but it turns off a lot of older folks like myself who know it isn't and that community matters.

gl to you and people like you trying to get it back on track!

Re: OCaml as my primary language

#92
ocaml is one of my favourite languages too, but I've found myself being drawn towards rust for my latest project due to its major superpower - you can write a rust library that looks like a c library from the outside, and can be called from other languages via their existing c ffi mechanisms. I feel like by writing the library in ocaml I would have a better experience developing it, but be giving up on that free interop.

Re: OCaml as my primary language

#93
post #71

I'm sure there's merit to the language, but the syntax seems absolutely alien to me. Some attempt to look like verbose imperative code, a bunch of semicolons, and for some strange reason, hate of parenthesis. Real life sample: let print_expr exp = (* Local function definitions *) let open_paren prec op_prec = if prec > op_prec then print_string "(" in let close_paren prec op_prec = if prec > op_prec then print_string…

I mean, I guess it depends on your background, but that code looks pretty nice compared to how it would look in a language without pattern matching and ADTs. This is why the MLs excel for things like parsers, interpreters, and compilers. Beauty is in the eye of the beholder, I guess. I suspect that if you gave it a bit of time it would start to really grow on you - that's how it was in my case. At first: "WTF is this…

I don't find the ADT and matching part weird, but rather everything else (as mentioned).

Re: OCaml as my primary language

#94
post #71

I'm sure there's merit to the language, but the syntax seems absolutely alien to me. Some attempt to look like verbose imperative code, a bunch of semicolons, and for some strange reason, hate of parenthesis. Real life sample: let print_expr exp = (* Local function definitions *) let open_paren prec op_prec = if prec > op_prec then print_string "(" in let close_paren prec op_prec = if prec > op_prec then print_string…

`let` defines a value. Some values are "plain old values", some are functions.

The syntax is `let = in ;;` where `expression` can also have `let` bindings.

So you can have

  let one = 1 in
  let two = 2 in
  let three = one + two in
  print_endline (string_of_int three);;

Re: OCaml as my primary language

#95
post #41

I wish somebody with this amount of experience would compare the benefits / shortcomings of using the ReasonML syntax. (The article mentions it once, in passing.)

What I missed most were let bindings (https://ocaml.org/manual/5.3/bindingops.html)

ReasonML has custom operators that allows for manipulating monads somewhat sanely (>>= operators and whatnot). rescript (reasonml’s “fork”) did not last time I checked. But it does have an async/await syntax which helps a lot with async code. reasonml did not last time I checked, so you had to use raw promises.

I believe Melange (which the article briefly talks about) supports let bindings with the reason syntax.

And this kinda changes everything if you React. Because you can now have sane JSX with let bindings. Which you could not until melange. Indeed, you can PPX your way out of it in ocaml syntax, but I’m not sure the syntax highlight works well in code editors. It did not on mine anyway last time I checked.

So for frontend coding, Melange’s reason ml is great as you have both, and let bindings can approximate quite well async syntax on top of writing readable monadic code.

For backend code, as a pythonista, I hate curlies. and I do like parenthesis-less function calls and definitions a lot. But I still have a lot of trouble, as a beginner ocamler, with non-variable function argument as I need to do “weird” parenthesis stuff.

Hope this “helps”!

Re: OCaml as my primary language

#96
post #41

I wish somebody with this amount of experience would compare the benefits / shortcomings of using the ReasonML syntax. (The article mentions it once, in passing.)

Sorry, I never used ReasonML so I don't see any advantage of using ReasonML except it had the time to die twice in 4 years :)

Re: OCaml as my primary language

#97

Question about terminology: Is it common to call higher-order function types "exponential types" as the article does? I know what higher-order functions are, but am having trouble grasping why the types would be called "exponential".

A first-order function type is already exponential. A sum type has as many possible values as the sum of its cases. E.g. `A of bool | B of bool` has 2+2=4 values. Similarly for product types and exponential types. E.g. the type bool -> bool has 2^2=4 values (id, not, const true, const false) if you don't think about side effects.

> bool -> bool has 2^2=4 values

Not the best example since 2*2=4 also.

How about this bit of Haskell:

  f :: Bool -> Maybe Bool
That's 3 ^ 2 = 9, right?

  f False = Nothing
  f False = Just True
  f False = Just False
  f True = Nothing
  f True = Just True
  f True = Just False
Those are 6. What would be the other 3? or should it actually be a*b=6?

EDIT: Nevermind, I counted wrong. Here are the 9:

  f x = case x of
    True -> Nothing
    False -> Nothing

  f x = case x of
    True -> Nothing
    False -> Just False

  f x = case x of
    True -> Nothing
    False -> Just True

  f x = case x of
    True -> Just False
    False -> Nothing

  f x = case x of
    True -> Just False
    False -> Just False

  f x = case x of
    True -> Just False
    False -> Just True

  f x = case x of
    True -> Just True
    False -> Nothing

  f x = case x of
    True -> Just True
    False -> Just False

  f x = case x of
    True -> Just True
    False -> Just True

Re: OCaml as my primary language

#98
post #71

I'm sure there's merit to the language, but the syntax seems absolutely alien to me. Some attempt to look like verbose imperative code, a bunch of semicolons, and for some strange reason, hate of parenthesis. Real life sample: let print_expr exp = (* Local function definitions *) let open_paren prec op_prec = if prec > op_prec then print_string "(" in let close_paren prec op_prec = if prec > op_prec then print_string…

It also uses double semicolon because single semicolon is already used as statement separator kinda like C. So double semicolon is top-level statement terminator.

Re: OCaml as my primary language

#99
post #13

Earlier quoted context omitted.

In the specific case of OCaml, this is also possible using indexing and GADTs or polymorphic variants. But generally, referencing as its own type serves different purposes. From my point of view, distinguishing between sum branches often tends to result in code that is difficult to reason about and difficult to generalise due to concerns about variance and loss of type equality.

Unless you reach an unsound part of the type system I don't see how. Could you provide an example?

- You can use GADTs (https://ocaml.org/manual/5.2/gadts-tutorial.html) and indexes to give a concrete type to every constructors:

  ```ocaml
  type _ treated_as = 
   | Int : int -> int treated_as
   | Float : float -> float treated_as

  let f (Int x) = x + 1 (* val f : int treated_as -> int *)
  ```
- You can use the structurale nature of polymorphic variants (https://ocaml.org/manual/5.1/polyvariant.html)

  ```ocaml
  let f = function 
  | `Foo x -> string_of_int (x + 1) 
  | `Bar x -> x ^ "Hello"
  (* val f : [ string` *)

  let g = function
  | `Foo _ -> ()
  | _ -> () 
  (* val g : [> `Foo of 'a ] -> unit *)
  ```
(Notice the difference between `>` and `And since OCaml has also an object model, you can also encoding sum and sealing using modules (and private type abreviation).

Re: OCaml as my primary language

#100
post #6

I haven't worked in OCaml but I have worked a bit in F# and found it to be a pleasant experience. One thing I am wondering about in the age of LLMs is if we should all take a harder look at functional languages again. My thought is that if FP languages like OCaml / Haskell / etc. let us compress a lot of information into a small amount of text, then that's better for the context window. Possibly we might be able to p…

In Scala, I've had excellent luck using LLMs to speed up development when I'm using cats-effect, an effects library.

My experience in the past with something like cats-effect has been that there are straightforward things that aren't obvious, and if you haven't been using it recently, and maybe even if you've been using it but haven't solved a similar problem recently, you can get stuck trawling through the docs squinting at type signatures looking for what turns out to be, in hindsight, an elegant and simple solution. LLMs have vastly reduced this kind of friction. I just ask, "In cats-effect, how do I...?" and 80% of the time the answer gets me immediately unstuck. The other 20% of the time I provide clarifying context or ask a different LLM.

I haven't done enough maintenance coding yet to know if this will radically shift my view of the cost/benefit of functional programming with effects, but I'm very excited. Writing cats-effect code has always been satisfying and frustrating in equal measure, and so far, I'm getting the confidence and correctness with a fraction of the frustration.

I haven't unleashed Claude Code on any cats-effect code yet. I'm curious to see how well it will do.

Post reply on HN