2013-08-15 8 views
7

मैं स्केलज़ में ST के साथ बस थोड़ा सा खेल रहा था और उस बिंदु पर आया, जहां मैं अपने STRef को संशोधित करने के लिए एक ट्रैवर्सबल प्रकार की सामग्री का उपयोग करना चाहता था। हास्केल में मैं कर सकता है कि इस प्रकार (हास्केल विकी से लिया गया):स्कालाज़ के लिए समकक्ष एमएम

sumST :: Num a => [a] -> a 
sumST xs = runST $ do 

    n <- newSTRef 0 

    forM_ xs $ \x -> do 
     modifySTRef n (+x) 

    readSTRef n 

दुर्भाग्य से मैं scalaz में forM_ के लिए बराबर ढूँढने में सक्षम नहीं किया गया। तो सवाल यह है कि मैं इसे स्केलज़ के साथ कैसे कर सकता हूं?

उत्तर

6

आप शायद जानते हैं, forM_mapM_ के फ़्लिप संस्करण है।

आप उपयोग कर सकते हैं traverse और traverse_ (जो Scalaz में लागू कर रहे हैं), mapM और mapM_ की सामान्यीकृत संस्करण के रूप में।

सबूत के रूप में, Data.Traversabletraverse के संदर्भ में mapM का अपना कार्यान्वयन निर्यात करता है।

sumST का एक scalaz संस्करण इस प्रकार दिखाई देंगे:

def sumST[S, A](as: List[A])(implicit A: Numeric[A]): ST[S, A] = 
    for { n <- newVar(A.zero) 
     _ <- as.traverseU(a => n.mod(A.plus(_, a))) 
     m <- n.read } yield m 

def sum[A : Numeric](as: List[A]): A = 
    runST(new Forall[({type λ[S] = ST[S, A]})#λ] { 
    def apply[S] = sumST[S, A](as) 
    }) 

सोच क्यों यह इतना Haskell संस्करण की तुलना में अधिक वर्बोज़ है पाठकों के लिए: हम एक रैंक -2 बहुरूपी प्रकार का प्रतिनिधित्व करने के Forall विशेषता का उपयोग करना चाहिए स्कैला में एक पूर्ण स्पष्टीकरण के लिए http://apocalisp.wordpress.com/2011/03/20/towards-an-effect-system-in-scala-part-1/ देखें।

+0

बिल्कुल सही, आपको बहुत बहुत धन्यवाद! – drexin

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