2014-07-14 6 views
5

यहाँ का उपयोग कोड है:एक monadic रैंक -2 प्रकार

{-# LANGUAGE RankNTypes, FlexibleContexts, ScopedTypeVariables #-} 

module Foo where 

import Data.Vector.Generic.Mutable as M 
import Data.Vector.Generic as V 
import Control.Monad.ST 
import Control.Monad.Primitive 
import Control.Monad 

data DimFun v s r = 
    DimFun {dim::Int, func :: v (PrimState s) r -> s()} 

runFun :: (Vector v r) => 
    (forall s . (PrimMonad s) => DimFun (Mutable v) s r) -> v r -> v r 
runFun t x = runST $ do 
    y <- thaw x 
    evalFun t y 
    unsafeFreeze y 

evalFun :: (PrimMonad s, MVector v r) => DimFun v s r -> v (PrimState s) r -> s() 
evalFun (DimFun dim f) y | dim == M.length y = f y 

fm :: (MVector v r, PrimMonad s, Num r, Monad m) => m (DimFun v s r) 
fm = error "" 

f :: forall v r m . (Vector v r, Num r, Monad m) => m (v r -> v r) 
f = liftM runFun $ (fm :: forall s . (PrimMonad s) => m (DimFun (Mutable v) s r)) 

यह त्रुटियों में परिणाम:

Couldn't match type ‘DimFun (Mutable v) s0 r’ 
       with ‘forall (s :: * -> *). PrimMonad s => DimFun (Mutable v) s r’ 
Expected type: DimFun (Mutable v) s0 r -> v r -> v r 
    Actual type: (forall (s :: * -> *). 
       PrimMonad s => 
       DimFun (Mutable v) s r) 
       -> v r -> v r 
Relevant bindings include 
    f :: m (v r -> v r) (bound at Testing/Foo.hs:36:1) 
In the first argument of ‘liftM’, namely ‘runFun’ 
In the expression: liftM runFun 

हालांकि, मुझे यकीन है कि ठीक करने या समस्या का निदान करने के लिए कैसे नहीं हूँ। यह एक अच्छी जगह (और अच्छी तरह से लिखित) प्रकार हस्ताक्षर के रूप में सरल हो सकता है।

यह पता लगाने की क्या चल रहा था की कोशिश में, मैं एक गैर monadic संस्करण (मेरे लिए बेकार) लिखते हैं, लेकिन यह संकलित:

gm :: (MVector v r, PrimMonad s, Num r) => DimFun v s r 
gm = error "" 

g :: forall v r m . (Vector v r, Num r) => v r -> v r 
g = runFun (gm :: forall s . (PrimMonad s) => DimFun (Mutable v) s r) 

यह मैं बात करता है त्रुटि ऊपर this question से संबंधित है जहां शब्दकोश जाने के लिए कोई जगह नहीं है, लेकिन यह वास्तव में अंधेरे में सिर्फ एक स्टैब है।

+0

ऐसा लगता है कि एक डबल पोस्ट किया है हो सकता है। इसे शायद हटा दिया जाना चाहिए और उत्तर यहां जाएं: http://stackoverflow.com/questions/24744294/pattern-matching-on-rank-2-type – jberryman

+0

@jberryman यह मेरे लिए स्पष्ट नहीं है कि इन दो प्रश्नों में समस्याएं संबंधित हैं (हालांकि कोड का कुछ सबसेट वास्तव में वही है)। यही कारण है कि मैंने दो प्रश्नों के रूप में पोस्ट किया। – crockeea

+0

पहले तर्क के प्रकार को ठीक करने के लिए स्कॉप्ड प्रकार चर का उपयोग करें। साथ ही, 'रनफन' के प्रकार में वैश्विक दायरे में 'फॉरल' को फैक्टर करने का प्रयास करें। – nomen

उत्तर

4

एक समाधान DimFun डेटाप्रकार अंदर PrimMonad बाधा स्थानांतरित करने के लिए है।

data DimFun v r = DimFun 
    { dim :: Int 
    , func :: forall s . PrimMonad s => v (PrimState s) r -> s() 
    } 

अपने कोड के बाकी को संकलित रूप में किया जाता है, को दूर करने DimFun से s पैरामीटर:

runFun :: Vector v r => DimFun (Mutable v) r -> v r -> v r 
runFun = ... 

evalFun :: (PrimMonad s, MVector v r) => DimFun v r -> v (PrimState s) r -> s() 
evalFun = ... 

fm :: (MVector v r, Num r, Monad m) => m (DimFun v r) 
fm = ... 

f :: (Vector v r, Num r, Monad m) => m (v r -> v r) 
f = liftM runFun fm 

डेटाप्रकार में वर्ग बाधा बढ़ते आप के लिए डरावना लग सकता है, लेकिन वास्तव में, आप पहले से ही वैसे भी वर्ग की बाधा थी। PrimStatePrimMonad का एक संबद्ध प्रकार का परिवार है, इसलिए v (PrimState s) r का उत्पादन या उपभोग करने के लिए, आपको PrimMonad बाधा की आवश्यकता है।

यदि आप इसे टालना चाहते हैं, तो आपको कुछ प्रकार बदलना होगा। यह देखने के लिए क्यों समारोह आप illtyped है, निम्न (जो ImpredictiveTypes की आवश्यकता है) पर विचार करें:

fm :: (MVector v r, PrimMonad s, Num r, Monad m) => m (DimFun v s r) 
fm = error "" 

g :: (Vector v r, Monad m) 
    => m (forall s . PrimMonad s => DimFun (Mutable v) s r) -> m (v r -> v r) 
g = liftM runFun 

यह साफ किया जाना चाहिए क्यों g fm illtyped है: g कुछ जहां forall s . PrimMonad s => अंदर m है उम्मीद है, जो fm के मामले में नहीं। आप प्रकार की एक समारोह लिखने के लिए करना होगा:

fm' :: (MVector v r, Monad m, Num r) => m (forall s . PrimMonad s => DimFun v s r) 
fm' = error "" 

f :: forall v r m . (Vector v r, Num r, Monad m) => m (v r -> v r) 
f = g fm' 
+0

उत्कृष्ट समाधान दोनों। मेरी इच्छा है कि यह और अधिक स्पष्ट था कि मुझे ऐसा करने की ज़रूरत थी! – crockeea

+0

यह [इस सवाल] का उत्तर भी देता है (http://stackoverflow.com/questions/24744294/pattern-matching-on-rank-2-type), क्योंकि अब मुझे रैंक -2 प्रकार पर पैटर्न मिलान करने की आवश्यकता नहीं है। एकमात्र अन्य चीज जो मैं पूछ सकता हूं वह इस बारे में एक युक्ति है कि मुझे यह कैसे पता होना चाहिए कि भविष्य में यह करना सही है। मुझे डेटा के बजाय डेटा के अंदर रैंक-2 प्रकार क्यों पसंद करना चाहिए? – crockeea

+1

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

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