2016-06-05 10 views
3

Eine Funktion, die ich nicht zurückkehrt Scalaz Reader,Scalaz Reader ReaderT

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

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

ich erstellen möchte eine neue Funktion auf findAccount(...) Basis ändern können ReaderT[Option, Session, A] wie in

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

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

zurückkehren, weil schließlich möchte ich dies tun,

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

Wie gehe ich vor? Macht das Sinn? Dank

vollständige Offenlegung,

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 

Antwort

2

Kurze Antwort: Sie können mapK verwenden.

Reader[A] ist ein Typalias für ReaderT[Id, A] und ReaderT ist ein Alias ​​für Kleisli. Id[A] ist das gleiche wie A.

Im Kleisli ScalaDoc wir finden mapK:

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

Da wir wissen, dass Reader[Session, A] die gleiche ist wie Kleisli[Id, Session, A] können wir mapK verwenden, um Kleisli[Option, Session, A] zu gehen:

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 
+0

Während ich nach Antworten gesucht Ich fand heraus, dass "Reader" und "ReaderT" Aliasnamen für "Kleisli" mit verschiedenen Konfigurationen sind, aber ich habe nicht genug Intelligenz, um die Punkte zu verbinden. Danke, dass Sie diese hervorgehoben haben. Ich verstehe mapK-Signatur, aber wissen Sie, wo ich weitere Beispiele mit MapK finden kann? – thlim

+1

Ich denke nicht, dass es viele Beispiele gibt, aber ich denke, die Signatur ist ziemlich selbsterklärend: gehe von einem 'Kleisli [M, A, B]' zu einem 'Kleisli [N, A, C]' mit a Funktion 'M [B] => N [C]'. Solange Sie eine solche Funktion definieren können, können Sie 'mapK' verwenden –