3

A function which I cannot change returns Scalaz Reader,

type Action[A] = Reader[Session, A]

def findAccount(s: String): Action[Account] = 
  Reader((session: Session) => Account(s))

I want create a new function based on findAccount(...) to return ReaderT[Option, Session, A] as in

type ActionT[A] = ReaderT[Option, Session, A]

def findAccountT(s: String): ActionT[Account] = findAccount(s).map(Option(_))

because eventually I want to do this,

def findAccBalT(accountNumber: String) = for {
  acc <- findAccountT(accountNumber)
  bal <- findBalanceT(acc)
}  yield bal

How do I proceed? Does it make sense? Thanks

Full disclosure,

import scalaz._
import Scalaz._        

trait Session {
  def doSomething(): Unit
}

case class Account(number: String) extends AnyVal
case class Amount(value: Int, currency: String) 
case class DBSession() extends Session {
  override def doSomething = println("writing to db")
}

type Action[A] = Reader[Session, A]
type ActionT[A] = ReaderT[Option, Session, A]

def findAccount(s: String): Action[Account] = 
  Reader((session: Session) => Account(s))

def findBalance(account: Account): Action[Amount] = 
  Reader((session: Session) => Amount(333, "S$"))

// failed
def findAccountT(s: String): ActionT[Account] = findAccount(s).map(Option(_))

// failed
def findBalanceT(account: Account): ActionT[Amount] = findBalance(account).map(Option(_))

// failed
def findAccBalT(accountNumber: String) = for {
  acc <- findAccountT(accountNumber)
  bal <- findBalanceT(acc)
}  yield bal
Peter Neyens
  • 9,770
  • 27
  • 33
thlim
  • 2,908
  • 3
  • 34
  • 57

1 Answers1

2

Short answer: You can use mapK.

Reader[A] is a type alias for ReaderT[Id, A] and ReaderT is an alias for Kleisli. Id[A] is the same as A.

In the Kleisli ScalaDoc we find mapK :

def mapK[N[_], C](f: (M[B]) => N[C]): Kleisli[N, A, C]

Since we know that Reader[Session, A] is the same as Kleisli[Id, Session, A] we can use mapK to go to Kleisli[Option, Session, A] :

import scalaz._, Scalaz._

type Session = String
type Action[A] = Reader[Session, A]
type ActionT[A] = ReaderT[Option, Session, A]

val action: Action[String] = Reader(s => s)
val actionT: ActionT[String] = action mapK Option.apply
Peter Neyens
  • 9,770
  • 27
  • 33
  • While I was searching for answers, I found out that `Reader` and `ReaderT` are aliases for `Kleisli` with different configurations but I do not have enough brain power to connect the dots. Thanks for pointing these out. I understand mapK signature but do you know where I can find more examples using mapK? – thlim Jun 05 '16 at 14:43
  • 1
    I don't think there are a lot of examples, but I think the signature is pretty self explanatory: go from a `Kleisli[M, A, B]` to a `Kleisli[N, A, C]` using a function `M[B] => N[C]`. As long as you can define such a function, you can use `mapK` – Peter Neyens Jun 05 '16 at 14:53