Showing posts with label scalaz. Show all posts
Showing posts with label scalaz. Show all posts

Monday, February 27, 2012

Having Fun with Monoid in Scalaz Seven

It's been some times since my last blog on Scalaz Seven that talks about Functor. You may have guessed that my second post on the series would be Applicative Functor. Well, sorry, I can't write in order yet, I prefer to talk about Monoid in Scalaz Seven instead. OK Let's have fun.

Having Fun With |+|
To start with, let's have some fun with |+| operator.

Let's start

scala> 6 |+| 7
res0: Int = 13

Well, not that interesting. It's just an addition. What about

scala> 6 + "9"
res2: String = 69

scala> 6 |+| "9"
<console>:14: error: type mismatch;
 found   : java.lang.String("9")
 required: Int
       6 |+| "9"

Not bad. |+| somehow protects you from adding integer to String. OK, not bad, but, not that fun. What about this:


scala> some(6) |+| some(9)
res9: Option[Int] = Some(15)

All right, that starts to be interesting. Give me more:

scala> some(6) |+| some(9) |+| some(10)
res10: Option[Int] = Some(25)


scala> some(6) |+| some(9) |+| some(10) |+| none[Int] |+| some(6)
res11: Option[Int] = Some(31)

Not bad at all. Want something more than that. Some String ?

scala> "Hello" |+| "World"

res25: java.lang.String = HelloWorld

scala> some("Hello") |+| some("World")

res26: java.lang.String = Some(HelloWorld)


What else do you have ? List ?


scala> List(2,4) |+| List(4, 5)
res28: List[Int] = List(2, 4, 4,5)

Cool. Boolean?


scala> val b = true
b: Boolean = true


scala> val c = true
c: Boolean = true


scala> b |+| c
<console>:24: error: value |+| is not a member of Boolean
       b |+| c
         ^

Ouch. Why ? Well, because |+| can be interpreted in conjunction or disjunction (note that, actually this works in Scalaz 6, not sure if scalaz seven will make it work as in scalaz 6). To fix this, let's do the following:


scala> val a = Conjunction(true)
a: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = true


scala> val b = Conjunction(true)
b: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = true


scala> val c = Conjunction(false)
c: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = false


scala> a |+| b
res34: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = true


scala> a |+| c
res35: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = false


scala> a |+| b |+| c
res36: scalaz.package.@@[Boolean,scalaz.Tags.Conjunction] = false

All right. That makes sense. What about Disjunction ? Well, just do the same.

scala> val e = Disjunction(true)
e: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = true


scala> val f = Disjunction(true)
f: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = true


scala> val g = Disjunction(false)
g: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = false


scala> val h = Disjunction(false)
h: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = false


scala> e |+| f
res37: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = true


scala> e |+| h
res38: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = true


scala> g |+| h
res39: scalaz.package.@@[Boolean,scalaz.Tags.Disjunction] = false

OK. That's cool, but it starts to be boring. Doesn't it? Give me something more spectacular.  What about Tuple?  All right, what about Tuple?

scala> (6, "Hello", List(4, 2)) |+| (7, "Hello", List(5))
res40: (Int, java.lang.String, List[Int]) = (13,HelloHello,List(4, 2, 5))

So, |+| actually "sums" each corresponding element of two tuples. That's quite cool. What if they are nested? Will it work ?

scala> (some(6), some("Hello"), (some(5), some(3))) |+| 
        (some(7), none[String], (some(6), none[Int]))

res43: (Option[Int], Option[java.lang.String], (Option[Int], Option[Int])) = 

(Some(13),Some(Hello),(Some(11), Some(3)))


Fantastic! Pretty cool.

[ I heard somebody there "you see, this Scalaz guy loves using funny operator. This time, they use |+|. OMG, That's not readable". All right, all right. You can actually change all |+| above with its alias called mappend, hope you're happier now].

Monoid and Semigroup Behind the Scene


Behind the scene, what happen is that Scalaz offers a quite simple but powerful abstraction, called Monoid. Believe me, Monoid is something quite simple: it's a type class with two functions: append and zero: 


1     
2      trait Monoid[A] { 
3        val zero: A 
4        def append(s1 : A, s2 : => A):A
5      } 


With the following contract (or a law, if you wish)


zero append x = x
x append zero = x
(x append y) append z = x append (y append z)


Scalaz provides several instances of Monoid (we have seen some of them in action above):

  • Int, Short, BigInt, BigDecimal, Byte, Short ...
  • Boolean conjunction and disjunction
  • List and Stream
  • String
  • Either.LeftProjection and Either.RightProjection.
  • ...
What about Option and Tuple ? Actually, Scalaz also provides some derived Monoid, like:
  • Option[A] is a monoid if A is monoid 
  • Tuple[A, B, C, D] is a monoid if A, B, C, and D is monoid
  • Map [A,B] is a monoid if B is a monoid
  • ...
Map is an interesting example. Let's try this:

scala> val m = Map("UO" -> BigDecimal(40.2),
     |              "US" -> BigDecimal(50.1),
     |              "YR" -> BigDecimal(10.1))
scala> val n = Map("UO" -> BigDecimal(10.2),
     |              "US" -> BigDecimal(40.0),
     |              "YZ" -> BigDecimal(10.5))
scala> m |+| n
res47: scala.collection.immutable.Map[java.lang.String,scala.math.BigDecimal] = Map(UO -> 50.4, US -
> 90.1, YZ -> 10.5, YR -> 10.1)

As you can see, |+| adds every corresponding element in m and n. If there's no corresponding element, for example "YR" in m and "YZ" in n, then it just puts the element in the result map.

All examples so far use append function of Monoid, but not zero. A type class with only append is called Semigroup. The function zero is useful when we want to fold a list of monoid, for example using suml function also provided by scalaz:

scala> val xs = List(some(2,4), some(1, 3), some(2, 10))
xs: List[Option[(Int, Int)]] = List(Some((2,4)), Some((1,3)), Some((2,10)))

scala> xs.suml
res48: Option[(Int, Int)] = Some((5,17))


Conclusion
Scalaz provides a cool thing called Semigroup and Monoid. With that, we can benefit the operator |+| and sum for their instances like Integer, String, List, and so on. But the main benefit is that Scalaz provides implementation of Monoid for Option, Tuple, and Map. You don't need to know what Monoid or Semigroup are to benefit all this. But, why should you avoid them ? It's a very simple stuff.

I hope you enjoy this very express introduction to Scalaz Seven Monoid. Who said Scalaz is complex ?
 I'm preparing more on this subject. So, stay tuned.


Wednesday, November 23, 2011

Scalaz Seven Functor Feels like Seven Samurai

Jason Zaugg and all his scalaz folks are working on scalaz seven at the moment. Although they have started quite a couple of times ago, I only had a chance to play with the library only today.

In case you don't know scalaz, it's actually a popular but often misunderstood library written in scala. It's not haskell standard library ported to scala, but it's highly inspired by the haskell standard library though. I recommend you to have a look here scalaz . One recommendation: take your time, don't be hurry to understand, otherwise you will end up associate scalaz to banana [1], to rabbit [2], or to ejb2 [3]. Of course, scalaz is not ready for production, because you know ... you cannot persist a scalaz object using Hibernate.

I start with one of the simplest scalaz type class, called Functor. It sounds scarry, right ? Don't worry, think of Functor as a way to lift a function that maps A to B to something that map "container" of A to "container" of B. If you have a function that maps, from int to int, say, a functor allows mapping from List of integer to a list of integer by mapping each element of the list.

Say, you have a function incr:

val incr:Int=>Int= x => x + 1

a Functor[List] allows you to map every element in a list using that function like this:

val xs = List(5, 6, 7)
Functor[List].map(xs, incr)   // 6, 7, 8

Well, yeah, is that all? No ! I can also have this:

val eitX:Either[String, Int] = Right(6)
val eitY:Either[String, Int] = Left("Err")
Functor[Either].map(eitX, incr) // Right(7)
Functor[Either].map(eitY, incr) // Left("Err")


It starts to be interesting right, because you don't have map for Either in Scala standard library. Fine, is it great ?  No, it sucks. Function[Either] or Function[List] suck. We don't want it. Fortunately, scalaz comes wi th some magics that simplify the thing

(wait a minute? Scalaz ? Simplifies something? You must be kidding ?)

With the super complex highly intelligent Scalaz (as it is perceived  by many), indeed life is simpler, we can directly write:


val eitX:Either[String, Int] = Right(6)
val eitY:Either[String, Int] = Left("Err")
eitX.map(incr)             // Right(7)
eitY.map(incr)             // Left("Err")

That works, because Either, List, Option are instances of Functor (you know, the container that allows you to lift a function).

Is that all ? No. There are something even more interesting. Imagine if we have a List of Option, is it a functor ? Oh yes, it turns out that the composition of functors is a functor. Let's check:

val listCompOpt = Functor[List].compose(Functor[Option])
val ys = List(Some(1), Some(3), None, Some(6))
val zs = listCompOpt.map(ys)(incr)  // List(Some(2), Some(4), None, Some(7))

Yeah! What about the product ?

val listOptProdF = Functor[List].product(Functor[Option])
val ts = (List(1,2),Some(1))
val us = (List(3,7, 2, 1),None)

listOptProdF.map(ts)(incr)   // (List(2, 3),Some(2))
listOptProdF.map(us)(incr)   // (List(4, 8, 3, 2),None)

Oh, Cool.

OK, to finish this post, scalaz-seven (at least the version I was playing with) provides a couple of interesting functions like strengthL, strengthR, and fpair.

Here they are:

val xEit:Either[String, Int] = Right(3)
val yEit:Either[String, Int] = Right(4)
println(xEit.strengthL("Help"))    // Right("Help",4)
println(yEit.strengthL("Help"))    // Right(("Help",3))
val xOpt:Option[Int] = Some(4)
val yOpt:Option[Int] = None
println(xOpt.strengthR("my godness"))   // Some(4, "my godness") println(yOpt.strengthR("My godness"))  // None

println(xOpt.fpair)     // Some(4,4)
println(xEit.fpair)     // Right(3,3)

I  hope to be able to come with other posts in this series. No promise, but stay tuned.

----------------
[1] Banana in this article context is not a scala or a java library, it is a fruit name. In case you're not familiar with it, check this article. You may wonder how could one wrongly associate scalaz with banana. Well, that may happen, who knows.

[2] Rabbit in this article context is not a scala or a java library, not even a cool javascript library, it is a name of an animal. Again, wikipedia is helpful in case you're not familiar with it. Well, again, it may happen that you associate scalaz to rabbit, who knows.

[3] EJB2 is a server side component, usually managed by the application server. It is used mainly in enterprise application, and by the way the 'E' is Enterprise. You should not wonder why you might associate scalaz to EJB2, it happened !