5

मैं हास्केल में ट्रांसड्यूसर कार्यान्वित इस प्रकार है:ट्रांसड्यूसर्स और monomorphism प्रतिबंध

{-# LANGUAGE RankNTypes #-} 

import Prelude hiding (foldr) 
import Data.Foldable 

type Reducer b a = a -> b -> b 
type Transducer a b = forall t. Reducer t b -> Reducer t a 

class Foldable c => Collection c where 
    insert :: a -> c a -> c a 
    empty :: c a 

reduce :: Collection c => Transducer a b -> c a -> c b 
reduce f = foldr (f insert) empty 

mapping :: (a -> b) -> Transducer a b 
mapping f g x = g (f x) 

अब मैं एक सामान्य map समारोह को परिभाषित करना चाहते। इसलिए मैं GHCi में उपरोक्त कोड को लोड:

Prelude> :load Transducer 
[1 of 1] Compiling Main    (Transducer.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> let map = reduce . mapping 

<interactive>:3:20: 
    Couldn't match type ‘Reducer t0 b1 -> Reducer t0 a1’ 
        with ‘forall t. Reducer t b -> Reducer t a’ 
    Expected type: (a1 -> b1) -> Transducer a b 
     Actual type: (a1 -> b1) -> Reducer t0 b1 -> Reducer t0 a1 
    Relevant bindings include 
     map :: (a1 -> b1) -> c a -> c b (bound at <interactive>:3:5) 
    In the second argument of ‘(.)’, namely ‘mapping’ 
    In the expression: reduce . mapping 
*Main> let map f = reduce (mapping f) 
*Main> :t map 
map :: Collection c => (a -> b) -> c a -> c b 

तो मैं map = reduce . mapping को परिभाषित नहीं कर सकते हैं। हालांकि, मैं map f = reduce (mapping f) परिभाषित कर सकता हूं।

मेरा मानना ​​है कि यह समस्या monomorphism प्रतिबंध के कारण होती है। मैं वास्तव में map f = reduce (mapping f) के बजाय map = reduce . mapping लिखना चाहूंगा। इसलिए, मेरे पास दो प्रश्न हैं:

  1. इस समस्या का कारण क्या है? क्या यह वास्तव में monomorphism प्रतिबंध है?
  2. मैं इस समस्या को कैसे ठीक करूं?
+1

यह उच्च रैंक के साथ प्रकार अनुमान के कारण है। Monomorphism प्रतिबंध यहाँ कोई फर्क नहीं पड़ता। कोई आसान फिक्स नहीं, मुझे लगता है कि एक प्रकार की एनोटेशन जोड़ने या एक पॉइंटफुल परिभाषा में जाने के अलावा। – chi

+0

एनोटेशन टाइप करें मदद नहीं करते: 'नक्शा :: संग्रह सी => (ए -> बी) -> सी ए -> सी बी; नक्शा एफ = कम (मैपिंग एफ) 'अभी भी एक ही त्रुटि उत्पन्न करता है। –

+0

टाइप त्रुटि आपको बताती है कि समस्या क्या है। 'मैपिंग' का प्रकार चुपचाप 'फोल' को बाईं ओर ले जाने के लिए चुपचाप बदल दिया गया है ('t: t mapping'' आज़माएं। यह एक मान्य (अर्थशास्त्र-संरक्षण) परिवर्तन है, लेकिन टाइपशेकर अपेक्षा करता है कि 'ट्रांसड्यूसर ए बी' उचित प्रकार, 'रेड्यूसर टी ए -> रेड्यूसर टी बी' (जो * विशिष्ट प्रकार हो सकता है)। लेकिन जब आप 'कम (मैपिंग एफ) लिखते हैं, तो टाइपशेकर देखता है कि' मैपिंग एफ 'के अनुप्रयोग में टाइप' टॉरल टी 'होना चाहिए। Reducer टी बी -> Reducer टी ए', जो 'कम करने' के लिए एक तर्क के लिए सही प्रकार है। – user2407038

उत्तर

4

आप Transducer एक newtype बनाने के लिए, की तुलना में GHC प्रकार काफी बेहतर बाहर काम करेंगे। मौजूदा प्रकार परिवर्तक दायरे से बच नहीं पाएंगे — ट्रांसड्यूसर पॉलिमॉर्फिक रहेगा।

दूसरे शब्दों में, नीचे परिभाषा map = reduce . mapping साथ में काम करता है

{-# LANGUAGE RankNTypes #-} 

import Prelude hiding (foldr, map, (.), id) 
import Control.Category 
import Data.Foldable 

type Reducer b a = a -> b -> b 
newtype Transducer a b = MkTrans { unTrans :: forall t. Reducer t b -> Reducer t a } 

class Foldable c => Collection c where 
    insert :: a -> c a -> c a 
    empty :: c a 

instance Collection [] where 
    insert = (:) 
    empty = [] 

reduce :: Collection c => Transducer a b -> c a -> c b 
reduce f = foldr (unTrans f insert) empty 

mapping :: (a -> b) -> Transducer a b 
mapping f = MkTrans $ \g x -> g (f x) 

filtering :: (a -> Bool) -> Transducer a a 
filtering f = MkTrans $ \g x y -> if f x then g x y else y 

map :: Collection c => (a -> b) -> c a -> c b 
map = reduce . mapping 

filter :: Collection c => (a -> Bool) -> c a -> c a 
filter = reduce . filtering 

instance Category Transducer where 
    id = MkTrans id 
    MkTrans f . MkTrans g = MkTrans $ \x -> g (f x) 

dub :: Num a => a -> a 
dub x = x + x 

test1 :: [Int] 
test1 = reduce (filtering even . mapping dub) [1..10] 
-- [2,4,6,8,10,12,14,16,18,20] 

test2 :: [Int] 
test2 = reduce (mapping dub . filtering even) [1..10] 
-- [4,8,12,16,20] 

*Main> :t reduce . mapping 
reduce . mapping :: Collection c => (a -> b) -> c a -> c b 

इसके अलावा, आप http://www.reddit.com/r/haskell/comments/2cv6l4/clojures_transducers_are_perverse_lenses/ जाँच करने के लिए जहां परिभाषा type Transducer a b =:: (a -> Constant (Endo x) a) -> (b -> Constant (Endo x) b) और विभिन्न अन्य है चाहता हूँ सकता है। अन्य रुचि चर्चा भी।

+0

यहाँ उचित यह एक' newtype' बनाने के लिए लगता है। हालांकि, 'लेंस' के साथ आप बहुत सारी चीज़ें खोल सकते हैं, सरल 'प्रकार' में खुले झूठ बोलने वाले 'फोरल' पर निर्भर करते हैं, और नए प्रकार के साथ काफी काम नहीं करेंगे। यह सुनिश्चित नहीं है कि ट्रांसड्यूसर के लिए भी यह मामला कितना हो सकता है। – leftaroundabout

+0

कंपोज़िंग ट्रांसड्यूसर उन्हें 'श्रेणी' बनाकर किया जा सकता है। – phadej

+0

संपादित एक सा जवाब देने, reddit जवाब – phadej

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