Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add monadic val #2

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Add monadic val #2

wants to merge 4 commits into from

Conversation

b-studios
Copy link
Owner

@b-studios b-studios commented Dec 2, 2018

WIP

Adding monadic value bindings to block syntax. That is,

{
  val a <- ma
  val b <- mb
  foo(a, b)
}

desugars to:

{
  ma.flatMap { a => 
  mb.flatMap { b => 
    foo(a, b)
  }}
}

More details can be found in the contributors forum.

@b-studios
Copy link
Owner Author

Here is another example of using the monadic val syntax:

trait Monad[+A] {
  def flatMap[B](f: A => Monad[B]): Monad[B]
}
def pure[A](a: A): Monad[A] = ???

val foo = 42
val ma: Monad[Int] = ???

val x: Monad[String] = {
  val a: Int <- ma
  println("real side effect")
  val b <- ma
  if (a == b) {
    pure("foo")
  } else {
    pure("bar")
  }
}

@nafg
Copy link

nafg commented Dec 2, 2018

Does the first statement of the block have to be a val ... <-? Because otherwise it means that as you're reading code you don't know what it does until later retroactively, when you encounter the val ... <- in the block.

@b-studios
Copy link
Owner Author

b-studios commented Dec 2, 2018

No, since the transformation really just desugars to flatMap ignorant of the rest of the block, the first statement does not need to be a monadic val.

@b-studios
Copy link
Owner Author

Also, all statements except for monadic binds just preserve their semantics. So, what you read is what you get ;)

@b-studios
Copy link
Owner Author

b-studios commented Dec 2, 2018

It would be nice to have syntax for monadic binds that ignore their results. That is, those which are only executed for their side effects.

Currently one has to write:

{
...
val _ <- log("foo")
val _ <- log("bar")
.. 
}

But I don't have a good proposal for a syntax there, yet. The best I could come up with is using do:

{
...
do log("foo")
do log("bar")
.. 
}

While it nicely fits as a marker that the rhs is monadic and is reminiscent of Haskell, it might not ideal to overload it as a keyword. It also will clash syntactically with do ... while ... expressions.

Any other ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants