News for hackers. Stuff that matters.
Re:Functional Semantics in Imperative Clothing (Richard Feld... by bradrn on Monday April 29, 2024 @08:45AM (#40197566)
I find it amusing that the system described in this article is simply what Haskell calls the ‘IO monad’. That is to say, it describes an IO system with the following ingredients:

1. Each IO operation returns a special value which denotes an IO action

2. These IO actions can be sequenced using a function which feeds an IO action to a continuation

3. Syntax sugar to remove the annoyance of explicitly writing the sequencing function

Together, (1) and (2) make this a monad; (3) in this article is just ‘do’-notation. The only major difference from Haskell is that Roc doesn’t generalise the idea to other monads, which makes it far less powerful than Haskell’s Monad typeclass.

Re:Functional Semantics in Imperative Clothing (Richard Feld... by garrinm on Monday April 29, 2024 @09:23AM (#40198027)
This gets discussed in the Roc community. They are exploring designing a language without higher kinded polymorphism.

Here's a snippet from the Roc FAQ.

> It's impossible for a programming language to be neutral on this. If the language doesn't support HKP, nobody can implement a Monad typeclass (or equivalent) in any way that can be expected to catch on. Advocacy to add HKP to the language will inevitably follow. If the language does support HKP, one or more alternate standard libraries built around monads will inevitably follow, along with corresponding cultural changes. (See Scala for example.) Culturally, to support HKP is to take a side, and to decline to support it is also to take a side.

https://www.roc-lang.org/faq.html#higher-kinded-polymorphism

Re:Functional Semantics in Imperative Clothing (Richard Feld... by Cyrus_T on Monday April 29, 2024 @11:56AM (#40199964)
I feel like adding HKP isn't "taking a side" nearly as much as not adding HKP to turn people away because you don't like their cultural contribution.

By adding the feature you aren't actually excluding the people who don't want to use it. They are free to avoid it and maintain parallel ecosystems where HKP is avoided.

You are only excluding them if the standard library forces them to interact with HKP code, which arguably Haskell does, and it makes a PITA for teaching it. Haskell however isn't doing it with the intention of exclusion.

On the other hand, not adding the feature because you don't like the culture it brings is intentionally exclusionary. You're intentionally taking a side against certain kinds of people and the certain kinds of code they want to be able to express without repetition... and you're hamstringing the expressibility of your language to do it.

I completely understand wanting to avoid HKP for teaching purposes, but maybe that is a problem that could better be resolved by always providing monomorphic options for standard library functions....

But avoiding HKP to avoid a certain kind of culture? Well now it's personal!

Re:Functional Semantics in Imperative Clothing (Richard Feld... by rtfeldman on Monday April 29, 2024 @01:49PM (#40201604)
As the FAQ entry notes, one of the "sides" in the design space here is "a fragmented ecosystem is best because there's no other way to accommodate the variety of different styles people want to use" - this is a totally reasonable preference to have!

Still, hopefully it's clear why a language designer might want to go down a different path. After all, it's also totally reasonable to prefer an ecosystem which isn't fragmented along these lines (the way it is in, say, Scala) even though it means fewer different programming styles are supported.

Re:Functional Semantics in Imperative Clothing (Richard Feld... by tkz1312 on Monday April 29, 2024 @09:26AM (#40198052)
Roc has algebraic effects instead of Monads for effect tracking. The two systems are exactly as expressive as each other [1]. Algebraic effects compose better than Monads, and are probably more beginner friendly. Imo Monadic code can be a little easier to follow sometimes since there’s less non-local control flow. They are both great things to have in a language and I’m super excited to see how much progress Roc is making in both approachability and performance when it comes to pure functional programming.

[1]: https://homepages.inf.ed.ac.uk/slindley/papers/effmondel-jfp...

Re:Functional Semantics in Imperative Clothing (Richard Feld... by rtfeldman on Monday April 29, 2024 @10:30AM (#40198783)
Roc actually doesn't use algebraic effects under the hood, although errors can naturally accumulate in a way that makes the code look more like error handling in algebraic effects systems:

https://www.roc-lang.org/tutorial#task-failure

The implementation detail that makes this error handling possible is that Roc uses anonymous sum types called "tags" (OCaml calls them polymorphic variants) that can accumulate on the fly:

https://www.roc-lang.org/tutorial#tags

Re:Functional Semantics in Imperative Clothing (Richard Feld... by tkz1312 on Monday April 29, 2024 @11:06AM (#40199276)
Very interesting, thanks for the clarification. What is the difference between algebraic effects and rocs approach?
Re:Functional Semantics in Imperative Clothing (Richard Feld... by rtfeldman on Monday April 29, 2024 @11:23AM (#40199527)
In Haskell terms, Roc's `Task ok err` is essentially an `IO (Either err ok)` - the only difference between how Roc does it and how Haskell does it is that `Task` bakes in error handling whereas `IO` doesn't. (Plus the syntax sugar being different, of course.)

So the biggest difference is that algebraic effects are a separate language feature, whereas Task (like IO in Haskell) is a plain old type in the standard library that happens to represent effeects.

Incidentally, the Task.await function in Roc is based on Elm's Task.andThen - we just tried out a different name and argument order for it:

https://package.elm-lang.org/packages/elm/core/latest/Task#a...

Re:Functional Semantics in Imperative Clothing (Richard Feld... by bedobi on Monday April 29, 2024 @10:45AM (#40198998)
can someone explain in plain English and with some easy to understand code examples?
Re:Functional Semantics in Imperative Clothing (Richard Feld... by ngruhn on Monday April 29, 2024 @11:13AM (#40199380)
But do algebraic effects preserve referential transparency? It’s hard for me to see that they do.
Re:Functional Semantics in Imperative Clothing (Richard Feld... by posix_monad on Monday April 29, 2024 @11:49AM (#40199872)
IIUIR, Roc's syntax is more ergonomic than do-notation.

In Roc, you can put a "!" (bind) pretty much anywhere, whereas in do-notation it must be part of a binding.

    current_user <- fetch_user
    manager <- fetch_manager current_user
Compared to

    manager <- fetch_manager (!fetch_user)
Please correct me if I'm wrong!
Re:Functional Semantics in Imperative Clothing (Richard Feld... by nyssos on Monday April 29, 2024 @11:44PM (#40207013)
You don't need to bind everything. The corresponding Haskell code is

    manager <- fetch_manager =<< fetch_user
Re:Functional Semantics in Imperative Clothing (Richard Feld... by posix_monad on Tuesday April 30, 2024 @09:24AM (#40210726)
Why have do-notation if we can use fancy operators for everything?

I think this version would is less approachable for most developers.

Re:Functional Semantics in Imperative Clothing (Richard Feld... by skulk on Monday April 29, 2024 @08:53AM (#40197665)
one advantage of this over do-notation is brought up in the article (though not explicitly): you can bind multiple things in a single expression. In Haskell, you'd have to do

    do x <- getx; y <- gety; x+y
In roc you can do

    getx! + gety!
which looks a bit cleaner.
Re:Functional Semantics in Imperative Clothing (Richard Feld... by bradrn on Monday April 29, 2024 @08:58AM (#40197718)
This is really just a matter of how much syntax sugar you want to implement. Idris already has precisely this syntax, and there’s a proposal to add it to Haskell too [0]. But none of this changes the core properties of the system which make it monadic.

[0] https://github.com/ghc-proposals/ghc-proposals/issues/527

Re:Functional Semantics in Imperative Clothing (Richard Feld... by rtfeldman on Monday April 29, 2024 @09:01AM (#40197753)
TIL that Idris also has a very similar `!` operator (in the prefix position instead of suffix) - thank you for sharing!
Re:Functional Semantics in Imperative Clothing (Richard Feld... by alipang on Monday April 29, 2024 @04:36PM (#40203816)
Even Javascript has a similar syntax, though `yield` / `await` only works for certain "monads" (promises seem close enough)
Re:Functional Semantics in Imperative Clothing (Richard Feld... by mrkeen on Monday April 29, 2024 @09:31AM (#40198115)

  (+) <$> getx <*> gety
Re:Functional Semantics in Imperative Clothing (Richard Feld... by superlopuh on Monday April 29, 2024 @11:23AM (#40199525)
Definitely doesn't look as clean as the example above, or as clean as the Swift equivalent of

    await x + y
Re:Functional Semantics in Imperative Clothing (Richard Feld... by mrkeen on Tuesday April 30, 2024 @05:37AM (#40208972)
The same syntax works across a range of constructs in Haskell, Scala and Idris.

  (+) <$> getx <*> gety
This could be:

* summing two reads in a Transaction,

* summing two parsed numbers in a Parser,

* summing two Nullable values into one Nullable value,

* producing a Validated<T> by validating two of its parts which require validation,

* and on and on.

It's even the cartesian product when run on lists:

  let suits = ["♠", "♥", "♦", "♣"]
  let nums  = concat [["A"], map show [2..10], ["J","Q","K"]]
  let cards = (++) <$> nums <*> suits

  putStrLn (unwords (take 15 cards))
  A♠ A♥ A♦ A♣ 2♠ 2♥ 2♦ 2♣ 3♠ 3♥ 3♦ 3♣ 4♠ 4♥ 4♦
Swift, Roc, Rust and JS have specialised their syntax for just one of these concerns.

Also, it looks like you can just do it with ! in Haskell: https://hackage.haskell.org/package/monadic-bang

Re:Functional Semantics in Imperative Clothing (Richard Feld... by tome on Tuesday April 30, 2024 @08:04AM (#40210088)
> it looks like you can just do it with ! in Haskell

Yes, although it's slightly clumsy.

    example = do
      let suits = ["♠", "♥", "♦", "♣"]
      let nums  = concat [["A"], map show [2..10], ["J","Q","K"]]
      let cards = do pure (!nums ++ !suits)
      putStrLn (unwords (take 15 cards))

    ghci> example 
    A♠ A♥ A♦ A♣ 2♠ 2♥ 2♦ 2♣ 3♠ 3♥ 3♦ 3♣ 4♠ 4♥ 4♦
Re:Functional Semantics in Imperative Clothing (Richard Feld... by jimbokun on Monday April 29, 2024 @11:02AM (#40199231)
The Roc version is still cleaner.