FFI के विशिष्ट मामले में, unsafePerformIO
, चीजें हैं जो गणितीय कार्य कर रहे हैं फोन करने के लिए इस्तेमाल किया जा करने के लिए है यानी उत्पादन निर्भर करता है केवल इनपुट पैरामीटर पर, और हर बार एक ही समारोह जानकारी के साथ कहा जाता है, यह वही आउटपुट वापस कर देगा। साथ ही, फ़ंक्शन पर साइड इफेक्ट्स नहीं होना चाहिए, जैसे कि डिस्क पर डेटा संशोधित करना या स्मृति को म्यूट करना।
उदाहरण के लिए से अधिकतर कार्यों को unsafePerformIO
के साथ बुलाया जा सकता है।
आप सही हैं कि unsafePerformIO
और पॉइंटर्स आमतौर पर मिश्रण नहीं करते हैं। उदाहरण के लिए, आप
p_sin(double *p) { return sin(*p); }
है भले ही आप सिर्फ एक सूचक से एक मूल्य पढ़ रहे हैं लगता है, यह unsafePerformIO
उपयोग करने के लिए सुरक्षित नहीं है। यदि आप p_sin
लपेटते हैं, तो एकाधिक कॉल पॉइंटर तर्क का उपयोग कर सकते हैं, लेकिन अलग-अलग परिणाम प्राप्त कर सकते हैं। यह सुनिश्चित करने के लिए कि यह सूचक अपडेट के संबंध में ठीक से अनुक्रमित है, यह सुनिश्चित करने के लिए फ़ंक्शन को IO
में रखना आवश्यक है।
यह उदाहरण स्पष्ट एक कारण बनाना चाहिए क्यों यह असुरक्षित है:
# file export.c
#include <math.h>
double p_sin(double *p) { return sin(*p); }
# file main.hs
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.Ptr
import Foreign.Marshal.Alloc
import Foreign.Storable
foreign import ccall "p_sin"
p_sin :: Ptr Double -> Double
foreign import ccall "p_sin"
safeSin :: Ptr Double -> IO Double
main :: IO()
main = do
p <- malloc
let sin1 = p_sin p
sin2 = safeSin p
poke p 0
putStrLn $ "unsafe: " ++ show sin1
sin2 >>= \x -> putStrLn $ "safe: " ++ show x
poke p 1
putStrLn $ "unsafe: " ++ show sin1
sin2 >>= \x -> putStrLn $ "safe: " ++ show x
जब संकलित, इस कार्यक्रम आउटपुट
$ ./main
unsafe: 0.0
safe: 0.0
unsafe: 0.0
safe: 0.8414709848078965
हालांकि सूचक द्वारा संदर्भित मूल्य दो संदर्भों के बीच बदल गया है "sin1" के लिए, अभिव्यक्ति का फिर से मूल्यांकन नहीं किया जाता है, जिससे बालों का उपयोग किया जा रहा है। चूंकि safeSin
(और इसलिए sin2
) आईओ में है, इसलिए प्रोग्राम को अभिव्यक्ति का पुनर्मूल्यांकन करने के लिए मजबूर किया जाता है, इसलिए अपडेट किए गए पॉइंटर डेटा का उपयोग इसके बजाय किया जाता है।
क्या आप विस्तारित कर सकते हैं कि पॉइंटर्स के साथ आपके उदाहरण में 'असुरक्षितफॉर्मियो' का उपयोग करना असुरक्षित क्यों है? –
@VladtheImpala - मैंने उम्मीदपूर्वक इसे और अधिक स्पष्ट रूप से संबोधित करने के लिए संपादित किया है। –
'unsafePerformIO' का उल्लेख आपके उत्तर में स्पष्ट रूप से नहीं किया गया है। क्या होगा यदि मैं 'unsafePerformIO' में' poke pz >> safeSin p' में अनुक्रमों को अनुक्रमित करता हूं: 'mySin z = unsafePerformIO (poke pz >> safeSin p)' और फिर 'mySin' को सामान्य फ़ंक्शन के रूप में उपयोग करें, मुझे चाहिए ठीक है, है ना? –