2012-09-10 30 views
11

मैं Seq[Option[A]] के xs के लिए xs के लिए if(xs.contains(None)) None else Some(xs.flatten) के रूप में प्राप्त करने के लिए मोनाड्स (और संभवतः मोनोइड्स) का उपयोग करने के लिए एक अधिक सामान्य समाधान की तलाश में हूं।ए [बी [सी]] से बी [ए [सी]] को कैसे परिवर्तित करें यदि ए और बी मोनैड हैं?

मैं स्कालज़ के साथ ऐसा कैसे कर सकता हूं? मुझे लगता है कि मुझे कुछ स्पष्ट याद आ रही है।

उत्तर

14

दो monads होने दोनों के लिए पर्याप्त नहीं (M के लिए) और पर्याप्त से अधिक (N के लिए) -which अप पर्याप्त नहीं कहते हैं, जाहिर है-लेकिन अगर M एक Traverse उदाहरण है और N एक Applicative उदाहरण है, आप कर सकते हैं है sequence का उपयोग करें। उदाहरण के लिए:

import scalaz._, Scalaz._ 

def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence 

इसमें आपके द्वारा अर्थात् अर्थशास्त्र है। ध्यान दें कि Seq के बजाय मैं List का उपयोग कर रहा हूं, क्योंकि स्कैलाज़ 7 अब के लिए आवश्यक Traverse उदाहरण प्रदान करता है (हालांकि आप आसानी से अपना लिख ​​सकते हैं)।


आपने ध्यान दिया होगा, निम्नलिखित संकलन नहीं होगा:

List(Some(1), Some(45)).sequence 

हालांकि यह ठीक है अगर तुम वहाँ में एक None फेंक:

scala> List(Some(1), None, Some(45)).sequence 
res0: Option[List[Int]] = None 

इसका कारण यह है अनुमानित है List(Some(1), Some(45)) का प्रकार List[Some[Int]] होगा, और हमारे पास उदाहरण Some के लिए नहीं है।

Scalaz एक आसान some विधि है कि Some.apply तरह काम करता है, लेकिन आप कुछ है जो पहले से ही एक Option के रूप में आपके द्वारा लिखा गया है देता है प्रदान करता है, ताकि आप निम्नलिखित लिख सकते हैं:

scala> List(some(1), some(45)).sequence 
res1: Option[List[Int]] = Some(List(1, 45)) 

कोई अतिरिक्त लिखना आवश्यक नहीं।

+0

स्कालज़ 7 के साथ आरईपीएल में यह विफल रहता है क्योंकि इसे सेक के लिए ट्रैवर्स टाइपक्लास उदाहरण नहीं मिल रहा है। शायद मुझे कुछ और आयात करना चाहिए? –

+0

आप 'सेक' के बजाय' सूची 'का उपयोग कर सकते हैं, या' सेक 'के लिए अपना स्वयं का उदाहरण प्रदान कर सकते हैं- मुझे यकीन नहीं है कि 'Seq' उदाहरण 7 में गायब क्यों हो गए हैं। –

+0

धन्यवाद, यह काम कर रहा है! लेकिन मैं इसके व्यवहार से निराश हूं: 'सेक' मुद्दे के अलावा एक और व्यक्ति आपको स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता है: 'वैल xs = सूची (कुछ (1), कुछ (45)); (एक्सएस: सूची [विकल्प [Int]]) अनुक्रम ' –