2013-08-23 7 views
7

मेरे पास एक मोनैड है जो एक संग्रह मोनैड के समान है। मैं वर्तमान में इसके लिए एक मोनाड ट्रांसफार्मर को लागू करने की कोशिश कर रहा हूं, लेकिन मैं असफल रहा हूं।स्कैला में 'सूची' मोनैड ट्रांसफार्मर को कैसे कार्यान्वित करें?

मैंने कार्यान्वयन Scalaz 6 और 7 में कार्यान्वित किया है, लेकिन मुझे समझ में नहीं आता कि यह कैसे काम करता है। यह कुछ अतिरिक्त प्रकार Step का उपयोग करता है, जिसका उद्देश्य मुझे अस्पष्ट नहीं है।

तो क्या कोई मुझे कृपया बता सकता है कि एक सूची मोनैड ट्रांसफॉर्मर को कैसे कार्यान्वित किया जाए, या तो Scalaz दृष्टिकोण या एक अलग कार्यान्वयन का उपयोग करके?

+1

7.x संस्करण 'चरण' का उपयोग नहीं करता है, यह बहुत सरल लगता है। https://github.com/scalaz/scalaz/blob/v7.0.3/core/src/main/scala/scalaz/ListT.scala – huynhjl

+0

@huynhjl ठीक है, मुझे यकीन था कि मैंने 'चरण' के साथ 7 कार्यान्वयन देखा है, हालांकि । – ziggystar

उत्तर

17

मुझे पूरा यकीन नहीं है, स्केलाज़ में कदम क्या है, लेकिन ListT को लागू करना काफी सीधे है। इस पर निर्भर करते हुए कि आप कितने संचालन करना चाहते हैं, यह थोड़ा काम हो सकता है, लेकिन मूल मोनैड ऑपरेशंस को निम्नानुसार कार्यान्वित किया जा सकता है।

पहले हम इकाई और functor के लिए typeclasses जरूरत है (हम भी अनुप्रयोगी जोड़ सकता है, लेकिन वह इस उदाहरण के लिए आवश्यक नहीं है):

trait Functor[F[_]] { 
    def map[A,B](fa: F[A])(f: A => B): F[B] 
} 

trait Monad[F[_]] extends Functor[F] { 
    def flatMap[A,B](fa: F[A])(f: A => F[B]): F[B] 
    def pure[A](x: A): F[A] 
} 

object Monad { 

    implicit object ListMonad extends Monad[List] { 
    def map[A,B](fa: List[A])(f: A => B) = fa map f 
    def flatMap[A,B](fa: List[A])(f: A => List[B]) = fa flatMap f 
    def pure[A](x: A) = x :: Nil 
    } 

    implicit object OptionMonad extends Monad[Option] { 
    def map[A,B](fa: Option[A])(f: A => B) = fa map f 
    def flatMap[A,B](fa: Option[A])(f: A => Option[B]) = fa flatMap f 
    def pure[A](x: A) = Some(x) 
    } 

    def apply[F[_] : Monad]: Monad[F] = implicitly[Monad[F]] 

} 

एक बार जब हम उन है, हम ट्रांसफार्मर, बना सकते हैं जो मूल रूप से बस F[List[A]] को लपेटता है और इसके बाद कॉलर को map और flatMap कॉल में फंक्शन पर map पर कॉल करके सूची में फ़ंक्शन और फिर map या flatMap resp कॉल पर कॉल करके कॉल करें। निहित List/एस पर।

final case class ListT[F[_] : Monad, A](fa: F[List[A]]) { 
    def map[B](f: A => B) = ListT(Monad[F].map(fa)(_ map f)) 

    def flatMap[B](f: A => ListT[F, B]) = ListT(Monad[F].flatMap(fa) { _ match { 
    case Nil => Monad[F].pure(List[B]()) 
    case list => list.map(f).reduce(_ ++ _).run 
    }}) 

    def ++(that: ListT[F,A]) = ListT(Monad[F].flatMap(fa) { list1 => 
    Monad[F].map(that.run)(list1 ++ _) 
    }) 

    def run = fa 
} 

एक बार जब हम को संशोधित करने के साथ किया जाता है, हम ListT वस्तु पर run विधि को फोन करके जिसके परिणामस्वरूप वस्तु प्राप्त कर सकते हैं। यदि आप चाहते हैं, तो आप स्केलज़ में अन्य सूची विशिष्ट संचालन भी जोड़ सकते हैं। यह बहुत सीधे आगे होना चाहिए। उदाहरण के लिए एक :: के रूप में दिखाई दे सकता है इस प्रकार है:

def ::(x: A) = ListT(Monad[F].map(fa)(x :: _)) 

उपयोग:

scala> ListT(Option(List(1,2,3))) 
res6: ListT[Option,Int] = ListT(Some(List(1, 2, 3))) 

scala> res6.map(_+45) 
res7: ListT[Option,Int] = ListT(Some(List(46, 47, 48))) 

scala> 13 :: res7 
res8: ListT[Option,Int] = ListT(Some(List(13, 46, 47, 48))) 

scala> res8.run 
res10: Option[List[Int]] = Some(List(13, 46, 47, 48)) 
1

मुझे लगता है कि scalaz.ListT scalaz 7.0.x और 7.1.x. में गलत है

https://github.com/scalaz/scalaz/issues/921

6.x संस्करण सही है। लेकिन यह StreamT जैसा ही है।

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