2015-11-19 6 views
5

Free के बाद से Scalaz 7.1.5 में एक इकाई के उदाहरण नहीं है, मैं उपयोगी विधि Applicative, Apply और इतने पर में परिभाषित का उपयोग नहीं कर सकते हैं।स्कालज़ 7.1.5 में मुफ़्त उदाहरण क्यों नहीं है?

/* ref - http://tpolecat.github.io/assets/sbtb-slides.pdf */ 
import Free._, Coyoneda._ 

type ResultSetIO[A] = FreeC[ResultSetOp, A] 

val next     : ResultSetIO[Boolean] = liftFC(Next) 
def getString(index: Int): ResultSetIO[String] = liftFC(GetString(index)) 
def getInt(index: Int) : ResultSetIO[Int]  = liftFC(GetInt(index)) 
def close    : ResultSetIO[Unit] = liftFC(Close) 

// compile errors 
def getPerson1: ResultSetIO[Person] = 
    (getString(1) |@| getInt(2)) { Person(_, _)} 

def getNextPerson: ResultSetIO[Person] = 
    next *> getPerson 

def getPeople(n: Int): ResultSetIO[List[Person]] = 
    getNextPerson.replicateM(n) // List.fill(n)(getNextPerson).sequence 

erorr संदेश है,

Error:(88, 19) value |@| is not a member of free.JDBC.ResultSetIO[String] 
(getString(1) |@| getInt(2)) { Person(_, _)} 
      ^
Error:(91, 10) value *> is not a member of free.JDBC.ResultSetIO[Boolean] 
next *> getPerson 
    ^
Error:(94, 19) value replicateM is not a member of free.JDBC.ResultSetIO[free.Person] 
getNextPerson.replicateM(n) // List.fill(n)(getNextPerson).sequence 
      ^

मैं Free के लिए इकाई उदाहरण को लागू करना चाहिए?

implicit val resultSetIOMonadInstance = new Monad[ResultSetIO] { 
    override def bind[A, B](fa: ResultSetIO[A])(f: (A) => ResultSetIO[B]): ResultSetIO[B] = 
    fa.flatMap(f) 

    override def point[A](a: => A): ResultSetIO[A] = 
    Free.point[CoyonedaF[ResultSetOp]#A, A](a) 
} 

या, क्या मुझे कुछ याद आ रही है? (उदाहरण आयात)

उत्तर

6

यह केवल स्केल कंपाइलर टाइप उपनामों के बारे में उग्र हो रहा है। आपके पास दो विकल्प हैं (या कम से कम दो विकल्प- शायद अन्य उचित कामकाज हैं)। सबसे पहले टाइप उपनाम को थोड़ा अलग तोड़ना है। इसके बजाय इस की:

type ResultSetIO[A] = FreeC[ResultSetOp, A] 

आप इस बारे में:

type CoyonedaResultSetOp[A] = Coyoneda[ResultSetOp, A] 
type ResultSetIO[A] = Free[CoyonedaResultSetOp, A] 

और फिर Monad[ResultSetIO] ठीक संकलित कर देगा। आप |@|, *>, और replicateM के लिए एक अतिरिक्त आयात की आवश्यकता होगी:

import scalaz.syntax.applicative._ 

अन्य विकल्प FreeC छोड़ने के लिए के रूप में यह है और इकाई उदाहरण परिभाषित खुद है, क्योंकि scalac यह तुम्हारे लिए नहीं मिल जाएगा। सौभाग्य से आप इसे आप के रूप में बाहर लिखने की तुलना में अधिक बस इस एक छोटे से कर सकते हैं का प्रस्ताव:

implicit val monadResultSetIO: Monad[ResultSetIO] = 
    Free.freeMonad[({ type L[x] = Coyoneda[ResultSetOp, x] })#L] 

मैं पहली दृष्टिकोण पसंद करते हैं, लेकिन यह वास्तव में जो आप का चयन नहीं करता है बात।

यहाँ सुविधा के लिए एक सरलीकृत पूरा काम कर उदाहरण है:

sealed trait ResultSetOp[A] 
case object Next extends ResultSetOp[Boolean] 
case class GetString(index: Int) extends ResultSetOp[String] 
case class GetInt(index: Int) extends ResultSetOp[Int] 
case object Close extends ResultSetOp[Unit] 

import scalaz.{ Free, Coyoneda, Monad } 
import scalaz.syntax.applicative._ 

type CoyonedaResultSetOp[A] = Coyoneda[ResultSetOp, A] 
type ResultSetIO[A] = Free[CoyonedaResultSetOp, A] 

val next: ResultSetIO[Boolean] = Free.liftFC(Next) 
def getString(index: Int): ResultSetIO[String] = Free.liftFC(GetString(index)) 
def getInt(index: Int): ResultSetIO[Int] = Free.liftFC(GetInt(index)) 
def close: ResultSetIO[Unit] = Free.liftFC(Close) 

case class Person(s: String, i: Int) 

def getPerson: ResultSetIO[Person] = (getString(1) |@| getInt(2))(Person(_, _)) 
def getNextPerson: ResultSetIO[Person] = next *> getPerson 
def getPeople(n: Int): ResultSetIO[List[Person]] = getNextPerson.replicateM(n) 

यह 7.1.5 के साथ ठीक संकलित कर देगा।


पूर्णता के लिए के लिए, वहाँ एक तीसरा रास्ता, संकलक FreeC संस्करण के लिए उदाहरणों को खोजने में मदद करने के लिए कुछ Unapply मशीनरी परिभाषित करने के लिए है जो (रोब नॉरिस इस कोड के लिए responsible है, जो मैं सिर्फ डी गए -kind पेश):

implicit def freeMonadC[FT[_[_], _], F[_]](implicit 
    ev: Functor[({ type L[x] = FT[F, x] })#L] 
) = Free.freeMonad[({ type L[x] = FT[F, x] })#L] 

implicit def unapplyMMFA[TC[_[_]], M0[_[_], _], M1[_[_], _], F0[_], A0](implicit 
    TC0: TC[({ type L[x] = M0[({ type L[x] = M1[F0, x] })#L, x] })#L] 
): Unapply[TC, M0[({ type L[x] = M1[F0, x] })#L, A0]] { 
    type M[X] = M0[({ type L[x] = M1[F0, x] })#L, X] 
    type A = A0 
} = new Unapply[TC, M0[({ type L[x] = M1[F0, x] })#L, A0]] { 
    type M[X] = M0[({ type L[x] = M1[F0, x] })#L, X] 
    type A = A0 
    def TC = TC0 
    def leibniz = Leibniz.refl 
} 

यह आपको इकाई उदाहरणों हर बार परिभाषित करने के बिना FreeC उपयोग करने के लिए अनुमति देता है। मुझे अभी भी लगता है कि FreeC पर छोड़ देना और Free का उपयोग करना एक बेहतर विचार है।

+1

ओह, और एक और: 4. वोट दें एसआई-5075, को याद करें, और इंतजार एक और चार या पांच साल ... –

+0

विस्तृत विवरण और उपयोगी अन्य विकल्प के लिए धन्यवाद। मैं पहली बार चुनना चाहता हूं क्योंकि स्कालाज़ 7.2.एक्स में 'फ्रीसी' नहीं है। – 1ambda

संबंधित मुद्दे