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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With