I'm trying to learn Scalaz with a toy project of mine, I used monads in Haskell and now I want to learn how to use them in Scala with Scalaz.
The big question is, how does one use the IO() Monad in the Scala's main method?
In Haskell, the main function is of type IO() and in Scala it is of type ().
The solution I found so far was to create another function foo of type IO() and in the main method call foo.unsafePerformIO(). But this makes me cringe.
What could be a solution?
Scalaz provides a SafeApp trait that allows you to replace Scala's side-effectful main method with a wrapper that looks more like Haskell's main:
import scalaz._, Scalaz._, effect.{ IO, SafeApp }
object MyMain extends SafeApp {
override def runl(args: List[String]): IO[Unit] = IO(println("hello world"))
}
Now MyMain can be used like any other JVM class with a static main.
I don't personally use SafeApp much, but it's there if you want to avoid calling unsafePerformIO by hand.
Scala's native main method is meant to be side effectful; calling unsafePerformIO in it is completely safe.
In fact, considering most Scala projects aren't 100% pure/Scalaz code, this approach is probably the most idiomatic one. Someone might have provided an "elegance" wrapper for it, but it wouldn't add any value besides cosmetics. And, again, most of the time you'd be embedding a Scalaz IO action inside a more mainstream, non-pure and possibly even non-functional Scala code anyway.
Furthermore, in general, and even in Haskell, the unsafe functions are typically just makeSureYouKnowWhatYoureDoing functions.
Related
Why is Scala designed with the following irritating form of boilerplate?
It would be convenient to write
def doStuffWithInts(ints: BaseIterable[Int]): Unit = ints foreach doStuffWithInt
for a common superclass BaseIterable of Iterable and ParIterable so that we can write both
val sequentialInts: Vector[Int] = getSomeHugeVector()
doStuffWithInts(sequentialInts)
and
val parInts: ParVector[Int] = getSomeHugeParVector()
doStuffWithInts(parInts)
Yet Scala forces us to copy and paste our doStuff method, once for Iterable and once for ParIterable. Why does Scala thrust such boilerplate on us by failing to have a common superclass BaseIterator of both Iterator and ParIterator?
You can use IterableOnce but that would force you to get an Iterator which is always sequential.
This is a conscious decision from the maintainers, you can read all the related discussions by starting here: https://github.com/scala/scala-parallel-collections/issues/101
The TL;DR; is that the maintainers agree that it is a bad idea to provide an abstraction between two; mainly because parallel collections should not be used as general collections but rather as localized optimizations. Also, the point out how easy it would be to introduce errors if you could abstract over the two (as was the case in 2.12).
Now, if you insist you want to abstract over the two, you may create your own typeclass.
Finally, I may suggest looking at using Future.traverse instead of parallel collections.
For me, I would use an implicit class under the following scenarios:
don't have access to the underlying type to be able to add the method I want.
the method I want doesn't make sense in a "global" sense.
i am splitting the functionality into another library of "extensions"
actually converting to a new type adds semantic/readability value (the new type actually means something)
However, I am fairly new to Scala (<6 months) and I'm noticing the developers around me are using implicit classes when it breaks the scenarios above. When I asked why, the answer was "because that's what I've always done".
So my question is, is there an official recommendation for when one should use an implicit class over a normal function added to the class definition? (I couldn't find anything here: https://docs.scala-lang.org/overviews/core/implicit-classes.html)
As per the SIP,
Motivation for the implicit class was that the popular extension method pattern, sometimes called the Pimp My Library pattern was used in Scala to extend pre-existing classes with new methods, fields, and interfaces.
There was also another common ‘extension’ use case known as type traits or type classes (see scala.math.Numeric). Type classes offered an alternative to pure inheritance hierarchies that was very similar to the extension method pattern.
The main drawback to both of these techniques was that they suffered the creation of an extra object at every invocation to gain the convenient syntax. This made these useful patterns unsuitable for use in performance-critical code. In these situations it was common to remove use of the pattern and resort to using an object with static helper methods.
And implicit class syntax was thus added to solve these issues.
The rock. They allow to make your own DSLs. Take a look to the Spray code, one of our classic and beloved projects:
trait TransformerPipelineSupport {
...
implicit class WithTransformation[A](value: A) {
def ~>[B](f: A ⇒ B): B = f(value)
}
...
}
The ~> allows to compose Spray directives... There are many more examples
I'm new to Scala, coming from Java, and I was just reading about traits. One thing that gets mentioned often is that traits don't (can't? won't?) have constructor parameters. I was curious to know if there was a reason for this.
Coming from a long ago maths/computer-science background I was was wondering if this was an inevitable consequence because of some language design decision, or if it was a conscious decision to avoid some inheritance/mix-in problem or another?
Was hoping someone might know because it feels like there might be something interesting behind the fact.
The other answers describe the language; I suspect your question may really be "why is it designed in this way".
I believe it arises out of the awkwardnesses and verboseness that would arise when extending multiple traits, especially with overrides and with types, and various mix-in strategies.
The Cake Pattern often results in various traits providing missing bits to each other in a way that is totally invisible - by design - in the mixing class. And mixing can be bi-directional, using self-types. So the construction of a class from traits can be a very messy business for the compiler. Scala often trades simplicity of compiler design and implementation for simplicity of language use and code reduction, and this is certainly a good example.
So while there may be simple, hierarchical cases where having a constructor might be useful and sufficient, it would almost certainly have to be redundant of other mechanisms for more difficult, non-hierarchical scenarios.
Scala 3 will allow trait parameters. Here's a sample from the docs
trait Greeting(val name: String) {
def msg = s"How are you, $name"
}
class C extends Greeting("Bob") {
println(msg)
}
The answer is: that's what Scala is right now.
But that might not be the case in the future: trait parameters can replace early initializers. (see Martin Odersky's recent Scala Days presentation page 34)
Scala: Where It Came From & Where It is Going
Traits don't have constructor parameters because traits cannot be constructed. Given any trait T it's not possible to instantiate any object of type exactly T. You can override trait defs with vals though, so
trait Foo {
def bar: String
}
class Baz(override val bar: String) extends Foo
You can't construct them directly because new MyTrait {} is actually sugar for an anonymous class of new Object with MyTrait {}
Trait is analog for Java Interface. The main difference is that trait can have default implementation for their methods.
So Java interfaces can't have constructor so do Scala traits
Scala 3 allows traits with parameters, just like classes have parameters.
I know what the monads are and how to use them. What I don't understand is what makes, let's say, Option a monad?
In Haskell a monad Maybe is a monad because it's instantiated from Monad class (which has at least 2 necessary functions return and bind that makes class Monad, indeed, a monad).
But in Scala we've got this:
sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }
Nothing related to a monad.
If I create my own class in Scala, will it be a monad by default? Why not?
Monad is a concept, an abstract interface if you will, that simply defines a way of composing data.
Option supports composition via flatMap, and that's pretty much everything that is needed to wear the "monad badge".
From a theoretical point of view, it should also:
support a unit operation (return, in Haskell terms) to create a monad out of a bare value, which in case of Option is the Some constructor
respect the monadic laws
but this is not strictly enforced by Scala.
Monads in scala are a much looser concept that in Haskell, and the approach is more practical.
The only thing monads are relevant for, from a language perspective, is the ability of being used in a for-comprehension.
flatMap is a basic requirement, and you can optionally provide map, withFilter and foreach.
However, there's no such thing as strict conformance to a Monad typeclass, like in Haskell.
Here's an example: let's define our own monad.
class MyMonad[A](value: A) {
def map[B](f: A => B) = new MyMonad(f(value))
def flatMap[B](f: A => MyMonad[B]) = f(value)
override def toString = value.toString
}
As you see, we're only implementing map and flatMap (well, and toString as a commodity).
Congratulations, we have a monad! Let's try it out:
scala> for {
a <- new MyMonad(2)
b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5
Nice! We are not doing any filtering, so we don't need to implement withFilter. Also since we're yielding a value, we don't need foreach either. Basically you implement whatever you wish to support, without strict requirements. If you try to filter in a for-comprehension and you haven't implemented withFilter, you'll simply get a compile-time error.
Anything that (partially) implements, through duck-typing, the FilterMonadic trait is considered to be a monad in Scala. This is different than how monads are represented in Haskell, or the Monad typeclass in scalaz. However, in order to benefit of the for comprehension syntactic sugar in Scala, an object has to expose some of the methods defined in the FilterMonadic trait.
Also, in Scala, the equivalent of the Haskell return function is the yield keyword used for producing values out of a for comprehension. The desugaring of yield is a call to the map method of the "monad".
The way I'd put it is that there's an emerging distinction between monads as a design pattern vs. a first-class abstraction. Haskell has the latter, in the form of the Monad type class. But if you have a type that has (or can implement) the monadic operations and obeys the laws, that's a monad as well.
These days you can see monads as a design pattern in Java 8's libraries. The Optional and Stream types in Java 8 come with a static of method that corresponds to Haskell return, and a flatMap method. There is however no Monad type.
Somewhere in between you also have the "duck-typed" approach, as Ionuț G. Stan's answer calls out. C# has this as well—LINQ syntax isn't tied to a specific type, but rather it can be used with any class that implements certain methods.
Scala, per se, does not provide the notion of a monad. You can express a monad as a typeclass but Scala also doesn't provide the notion of a typeclass. But Cats does. So you can create a Monad in Scala with the necessary boiler plate, e.g. traits and implicits cleverly used, or you can use cats which provides a monad trait out of the box. As a comparison, Haskel provides monads as part of the language. Regarding your specific question, an Option can be represented as a monad because it has a flatMap method and a unit method (wrapping a value in a Some or a Future, for example).
We are pretty familiar with implicits in Scala for now, but macros are pretty undiscovered area (at least for me) and, despite the presence of some great articles by Eugene Burmako, it is still not an easy material to just dive in.
In this particular question I'd like to find out if there is a possibility to achieve the analogous to the following code functionality using just macros:
implicit class Nonsense(val s: String) {
def ##(i:Int) = s.charAt(i)
}
So "asd" ## 0 will return 'a', for example. Can I implement macros that use infix notation? The reason to this is I'm writing a DSL for some already existing project and implicits allow making the API clear and concise, but whenever I write a new implicit class, I feel like introducing a new speed-reducing factor. And yes, I do know about value classes and stuff, I just think it would be really great if my DSL transformed into the underlying library API calls during compilation rather than in runtime.
TL;DR: can I replace implicits with macros while not changing the API? Can I write macros in infix form? Is there something even more suitable for this case? Is the trouble worth it?
UPD. To those advocating the value classes: in my case I have a little more than just a simple wrapper - they are often stacked. For example, I have an implicit class that takes some parameters, returns a lambda wrapping this parameters (i.e. partial function), and the second implicit class that is made specifically for wrapping this type of functions. I can achieve something like this:
a --> x ==> b
where first class wraps a and adds --> method, and the second one wraps the return type of a --> x and defines ==>(b). Plus it may really be the case when user creates considerable amount of objects in this fashion. I just don't know if this will be efficient, so if you could tell me that value classes cover this case - I'd be really glad to know that.
Back in the day (2.10.0-RC1) I had trouble using implicit classes for macros (sorry, I don't recollect why exactly) but the solution was to use:
an implicit def macro to convert to a class
define the infix operator as a def macro in that class
So something like the following might work for you:
implicit def toNonsense(s:String): Nonsense = macro ...
...
class Nonsense(...){
...
def ##(...):... = macro ...
...
}
That was pretty painful to implement. That being said, macro have become easier to implement since.
If you want to check what I did, because I'm not sure that applies to what you want to do, refer to this excerpt of my code (non-idiomatic style).
I won't address the relevance of that here, as it's been commented by others.