2016-06-05 3 views
3

функция, которую я не могу изменить возвращения Scalaz Reader,Scalaz читателя к ReaderT

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

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

Я хочу, чтобы создать новую функцию, основанную на findAccount(...) вернуть ReaderT[Option, Session, A] как в

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

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

, потому что в конце концов, я хочу сделать это,

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

Как мне продолжить? Имеет ли это смысл? Благодаря

Полное раскрытие,

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 

ответ

2

Короткий ответ: Вы можете использовать mapK.

Reader[A] является псевдонимом типа ReaderT[Id, A] и ReaderT является псевдонимом для Kleisli. Id[A] - это то же самое, что и A.

В Kleisli ScalaDoc мы находим mapK:

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

Поскольку мы знаем, что Reader[Session, A] такое же, как Kleisli[Id, Session, A] мы можем использовать mapK, чтобы перейти к 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 
+0

Пока я искал ответы , Я узнал, что «Читатель» и «Читатель» - это псевдонимы для «Kleisli» с разными конфигурациями, но у меня недостаточно энергии для подключения точек. Спасибо, что указали это. Я понимаю подпись mapK, но знаете ли вы, где я могу найти больше примеров, используя mapK? – thlim

+1

Я не думаю, что есть много примеров, но я думаю, что подпись довольно понятна: переходите от 'Kleisli [M, A, B]' к 'Kleisli [N, A, C]', используя функция 'M [B] => N [C]'. Пока вы можете определить такую ​​функцию, вы можете использовать 'mapK' –

Смежные вопросы