Direct translation of Haskell monad into Scala - scala

Trying to learn how to program monads in Scala, got some troubles
Given the quick code sample
import Control.Monad
newtype LJ a = LJ { session :: a }
instance Monad LJ where
return s = LJ s
(>>=) m f = f ( session m )
instance Functor LJ where
fmap f m = LJ . f $ session m
type SimpleLJ = LJ String
auth :: String -> String -> SimpleLJ
auth = undefined
readFeed :: String -> SimpleLJ
readFeed = undefined
closeFeed :: String -> SimpleLJ
closeFeed = undefined
proceed = auth "123" "456" >>= readFeed >>= closeFeed
how do I write the same thing in Scala (not scalaz)? As far as I learned, it's enough to implement map/flatMap methods in scala, but what is return here? And how to do binding without free variables in for statement?

Here's an almost direct translation, which I believe should answer your question. It's not completely direct because it doesn't utilize typeclasses which are present in form of a pattern in Scala, because in the current case it would have only overcomplicated things without a real reason.
case class LJ[A]( session : A ) {
// See it as Haskell's "fmap"
def map[B]( f : A => B ) : LJ[B] =
LJ( f( session ) )
// See it as Haskell's ">>="
def flatMap[B]( f : A => LJ[B] ) : LJ[B] =
f( session )
}
type SimpleLJ = LJ[String]
def auth( a : String, b : String ) : SimpleLJ = ???
def readFeed( a : String ) : SimpleLJ = ???
def closeFeed( a : String ) : SimpleLJ = ???
def proceed : SimpleLJ =
auth("123", "456").flatMap(readFeed).flatMap(closeFeed)
// Same as above but using a for-comprehension, which is
// used as a replacement for Haskell's "do"-block
def proceed2 : SimpleLJ =
for {
a <- auth("123", "456")
b <- readFeed(a)
c <- closeFeed(b)
}
yield c
This solution demonstrates a classical object-oriented approach. With this approach you can't have the return function encapsulated in the LJ type because you end up working on another level - not on a type as with typeclasses, but on the instance of a type. So the LJ case class constructor becomes the counterpart of return.

I would consider Nikita's answer to be the idiomatic translation (which should be preferred in real world situations, e.g. because of for-comprehension support), but it is definitely not the most "direct" one.
class LJ[A](val session : A)
trait Functor[F[_]] {
def fmap[A,B](fa:F[A])(f:A => B) : F[B]
}
trait Monad[M[_]] {
def pure[A](a:A):M[A]
def bind[A,B](ma:M[A])(f:A => M[B]):M[B]
}
object LJFunctor extends Functor[LJ] {
def fmap[A,B](lj:LJ[A])(f:A => B) = new LJ(f(lj.session))
}
object LJMonad extends Monad[LJ] {
def pure[A](a:A) = new LJ(a)
def bind[A,B](lj:LJ[A])(f:A => LJ[B]) = f(lj.session)
}
object MonadTest {
type SimpleLJ = LJ[String]
def auth(s:String, t:String):SimpleLJ = null
def readFeed(s:String):SimpleLJ = null
def closeFeed(s:String):SimpleLJ = null
val proceed = LJMonad.bind(LJMonad.bind(auth("123","456"))(readFeed _))(closeFeed _)
}
Note that you could add some syntactic sugar on top in order to get a nice (>>=) operator.

Related

What scala language feature is this using? It seems to extract values from a JsObject and cast it?

I'm just reading some scala source code to learn from, and I came accorss this:
How is o str "t" working here?
It seems to be extracting the "t" key from the JsObject and casting it to a string?
Try(Json parse str) map {
case o: JsObject =>
o str "t" flatMap {
case "p" => Some(Ping(o int "l"))
There are similar patters like:
case "opening" =>
for {
d <- o obj "d"
path <- d str "path"
fen <- d str "fen"
variant = dataVariant(d)
} yield Opening(variant, Path(path), FEN(fen))
Not sure what o obj "d" is doing? Or more importantly, how it is doing this?
I can't seem to find any scalaz references or package level implicits that would allow this?
Reference: https://github.com/ornicar/lila-ws/blob/master/src/main/scala/ipc/ClientOut.scala#L112
The expression o obj "d" uses combination of extension method via implicit conversion and infix notation. Desugared it translates to
augment(o).str("t")
where augment is defined by
final class LilaJsObject(private val js: JsObject) extends AnyVal {
def str(key: String): Option[String] =
(js \ key).asOpt[String]
...
}
object LilaJsObject {
implicit def augment(o: JsObject) = new LilaJsObject(o)
}
This low level implementation of extension method could be simplified using implicit classes
implicit final class LilaJsObject(private val js: JsObject) extends AnyVal {
def str(key: String): Option[String] =
(js \ key).asOpt[String]
}
In Scala 3 extension method syntax becomes even simpler.
Try seeing how infix punctuation-free notation desugars by executing
scala -Xprint:parser -e '"Hello" charAt 2'
which should display "Hello".charAt(2). Infix notation can lead to beautiful DSL, for example,
object repeat {
def it(n: Int) = new {
def times[A](f: => A): Unit = (1 to n).foreach(_ => f)
}
}
can express in almost human language
repeat it 5 times { println("hello") }

Play Framework / Dependent Future Composition

I am trying to do several dependent Slick/DB calls and then display the resulting data within a twirl template.
def show(slug: String) = Action.async { implicit rs =>
for {
f <- fooDAO.findBySlug(slug) // f is of type Option[foo]
fid <- f.flatMap(a => a.id.map(b => b)) // fid is of type Long
b <- barDAO.findByFooId(fid) // b is of type Seq[bar]
} yield {
f.map {
case Some(f) => Ok(views.html.foobar(f, b))
case _ => NotFound
}
}
}
I first need to get the "ID" to then be able to query other relevant data. The compiler is now producing this error:
play.sbt.PlayExceptions$CompilationException: Compilation error[type mismatch;
found : scala.concurrent.Future[Option[play.api.mvc.Result]]
required: Option[?]]
Any help would be greatly appreciated.
There is a fundamental flaw in your code, in that you're mixing in the same comprehension an Option and a Seq
A for-comprehension is expected to work on the same "container" type, which will be the resulting representation of the yield
e.g. if you combine several Options you get an Option, if you combine Seqs you get a Seq.
In this case you can overcome the problem by converting the Option (foo) to a Seq (which will be empty if the foo is None and have 1 element if not).
The end result would be
val results: Seq[(Foo, Bar)] =
for {
f <- fooDAO.findBySlug(slug).toSeq // f is of type Seq[Foo]
b <- barDAO.findByFooId(f.id) // b is of type Seq[Bar]
} yield (f, b)
But I guess this is not what you need. I suppose you want to get all Bars associated with the retrieved Foo, if any, and present it with your template. If no Foo is present for the slug, you want a NotFound.
We can do it like this
def show(slug: String) = Action.async { implicit rs =>
val f = fooDAO.findBySlug(slug) // f is of type Option[Foo]
f.fold(
NotFound,
foo => Ok(views.html.foobar(foo, barDAO.findByFooId(foo.id))
)
}
You can make it more explicit by defining a supporting method
def show(slug: String) = Action.async { implicit rs =>
def barsOf(f: Foo): Seq[Bar] = barDAO.findByFooId(f.id)
val f = fooDAO.findBySlug(slug) // f is of type Option[Foo]
f.fold(
NotFound,
foo => Ok(views.html.foobar(foo, barsOf(foo))
)
}
It's a bit tricky understanding what you're trying to achieve here, but if the whole thing is predicated on the findbySlug returning a Future[Option[Foo]] and the eventual outcome being a NotFound if that Option is a None, then your yield should probably just be:
...
} yield {
f.fold(NotFound)(foo => Ok(views.html.foobar(foo, b)))
}
Option[T] is a fantastic type for data-retrieval and control-flow, but pattern-matching on it is almost never the right approach. The use of fold feels nicely succinct for the task.

Assign an operator to a variable in Scala

Given this spinet of code in Scala:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = (d1, d2) => d1 ++ d2
That can be shortened to:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = _ ++ _
What actually the code does is renaming the operator ++ of Map[VertexId, Factor] and therefore: Is there a way to assign that operator to the variable? Like in this imaginary example:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++
And probably with type inference it would enough to write
val mapMerge = Map[VertexId,Factor].++
Thanks
Unfortunately, no, because the "operators" in Scala are instance methods — not functions from a typeclass, like in Haskell.
Whey you write _ ++ _, you are creating a new 2-argument function(lambda) with unnamed parameters. This is equivalent to (a, b) => a ++ b, which is in turn equivalent to (a, b) => a.++(b), but not to (a, b) => SomeClass.++(a, b).
You can emulate typeclasses by using implicit arguments (see "typeclasses in scala" presentation)
You can pass "operators" like functions — which are not really operators. And you can have operators which look the same. See this example:
object Main {
trait Concat[A] { def ++ (x: A, y: A): A }
implicit object IntConcat extends Concat[Int] {
override def ++ (x: Int, y: Int): Int = (x.toString + y.toString).toInt
}
implicit class ConcatOperators[A: Concat](x: A) {
def ++ (y: A) = implicitly[Concat[A]].++(x, y)
}
def main(args: Array[String]): Unit = {
val a = 1234
val b = 765
val c = a ++ b // Instance method from ConcatOperators — can be used with infix notation like other built-in "operators"
println(c)
val d = highOrderTest(a, b)(IntConcat.++) // 2-argument method from the typeclass instance
println(d)
// both calls to println print "1234765"
}
def highOrderTest[A](x: A, y: A)(fun: (A, A) => A) = fun(x, y)
}
Here we define Concat typeclass and create an implementation for Int and we use operator-like name for the method in typeclass.
Because you can implement a typeclass for any type, you can use such trick with any type — but that would require writing quite some supporting code, and sometimes it is not worth the result.

How to pass different functions fa, fb (different signatures, including returning type) as the same parameter into another function fc?

MWE (obs.: I am avoiding to have to instantiate a class every call of c, this is why functions are desired):
object Main extends App {
def a(s:String, i:Int) ={
s + i * i //some complex op that yields String
}
def b(i:Int) ={
i / 3 //another complex op that yields Int
}
def c(f: Any => Any) = {
val L = List(1,2,3,4) //list of complex elements
L map f //apply f within some complex loop
}
println(c(a))
/*
scala: type mismatch;
found : (String, Int) => String
required: Any => Any
println(c(a))
^
*/
println(c(b))
/*
scala: type mismatch;
found : Int => Int
required: Any => Any
println(c(b))
^
*/
}
Maybe an equivalent question would be "Is there some kind of function inheritance?",
like
def f
def fa(i: Int):String extends f
def fb(s: String):Int extends f
What you're trying to do isn't type-safe, since if it were you could pass a String to a function which takes an Int parameter:
e.g.
def c(f: Any => Any) = {
val L = List("a", "b", "c")
L map f
}
c(a)
However you can take a function of type Int => Any, since it is safe to assign a more derived type to Any.
def c(f: Int => Any) = {
val l = List(1,2,3,4)
l.map(f)
}
This is now safe:
val bList: List[Any] = c(b)
You still can't pass a to c however, since it requires two arguments instead of one. You can partially apply the first String argument and pass that:
val cList = c(a("SomeString", _:Int))
If you find yourself using Any,
you are probably doing something wrong, and
you most likely need generics.
In your case
def c[X,Y](f: X => Y) = { ... }
would probably do the trick, depending on what you have inside that complex loop.

Ternary Operator Similar To ?:

I am trying to avoid constructs like this:
val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result
Ok, in this example the then and else branch are simple, but you can image complex ones.
I built the following:
object TernaryOp {
class Ternary[T](t: T) {
def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
}
class Branch[T](branch: T => Boolean) {
def ?[R] (then: T => R) = new BranchThen(branch,then)
}
class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
class Elze[T,R](elze: T => R) {
def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
}
class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
implicit def any2Ternary[T](t: T) = new Ternary(t)
implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}
Defined that, I can replace the above simple example with:
this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}
But how can I get rid of the s: String =>? I want something like that:
this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}
I guess the compiler needs the extra stuff to infer types.
From Tony Morris' Lambda Blog:
I hear this question a lot. Yes it does. Instead of c ? p : q, it is
written if(c) p else q.
This may not be preferable. Perhaps you’d like to write it using the
same syntax as Java. Sadly, you can’t. This is because : is not a
valid identifier. Fear not, | is! Would you settle for this?
c ? p | q
Then you’ll need the following code. Notice the call-by-name (=>)
annotations on the arguments. This evaluation strategy is required to
correctly rewrite Java’s ternary operator. This cannot be done in Java
itself.
case class Bool(b: Boolean) {
def ?[X](t: => X) = new {
def |(f: => X) = if(b) t else f
}
}
object Bool {
implicit def BooleanBool(b: Boolean) = Bool(b)
}
Here is an example using the new operator that we just defined:
object T { val condition = true
import Bool._
// yay!
val x = condition ? "yes" | "no"
}
Have fun ;)
We can combine How to define a ternary operator in Scala which preserves leading tokens? with the answer to Is Option wrapping a value a good pattern? to get
scala> "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String
scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List
Is this adequate for your needs?
Rex Kerr’s answer expressed in basic Scala:
"Hi".getClass.getSimpleName match {
case x if x.endsWith("$") => x.init
case x => x
}
although I’m not sure what part of the if–else construct you want to optimise.
Since if-else constructions in Scala return a value, you can use this
val a = if (1 < 0) 1 else 2
More info: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples
Since : by itself won't be a valid operator unless you are ok with always escaping it with back ticks :, you could go with another character, e.g. "|" as in one of the answers above. But how about elvis with a goatee ?::
implicit class Question[T](predicate: => Boolean) {
def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5
Of course this again won't work if you values are lists, since they have :: operator themselves.