निम्नलिखित में:

import Data.Bifunctor
import qualified Data.ByteString.Lazy.UTF8 as BLU

safeReadFile :: FilePath -> ExceptT Text IO Text
safeReadFile p = (lift $ doesFileExist p) >>= bool (throwError "File does not exist") (lift $ pack <$> readFile p)

safeDecodeJSONFile :: FromJSON a => Text -> FilePath -> ExceptT Text IO a
safeDecodeJSONFile t f = do
  contents <- safeReadFile f
  tryRight $ first (\x -> pack (x ++ (unpack t))) (eitherDecode (BLU.fromString (unpack contents)))

जब मैं runExceptT $ safeDecodeJSONFile "something" "nonExistantFile.json" चलाता हूं तो मुझे Left "Does not exist something" मिलने की उम्मीद होती है, लेकिन इसके बजाय मुझे बस Left "Does not exist" मिलता है - मुझे पता है कि जिस फ़ंक्शन को मैं first में पास करता हूं, उसे निष्पादित किया जा रहा है, क्योंकि pack GHC शिकायत करता है कि ExceptT Text IO a के बजाय (eitherDecode (BLU.fromString (unpack contents))) का प्रकार ExceptT String IO a है - तो ++ से संयोजन भी क्यों नहीं होता है?

3
Cameron Ball 2 अगस्त 2019, 14:28

1 उत्तर

सबसे बढ़िया उत्तर

आपने लिखा है

safeDecodeJSONFile t f = do
  contents <- safeReadFile f
  tryRight $ ...

ExceptT के लिए Monad इंस्टेंस जैसे ही Left हिट करता है, ठीक वैसे ही वापस आ जाता है। तो tryRight ... कभी नहीं होता। आपको Left मामले को स्पष्ट रूप से संभालने की आवश्यकता है, शायद catchError का उपयोग करके।

जब तक हम इसमें हैं, तब भी एक समस्या है। आप लिखिए

safeReadFile :: FilePath -> ExceptT Text IO Text
safeReadFile p = (lift $ doesFileExist p) >>= bool (throwError "File does not exist") (lift $ pack <$> readFile p)

दुर्भाग्य से, यह विश्वसनीय नहीं है। सबसे पहले, फ़ाइल मौजूद नहीं है केवल एक कारण है कि इसे पढ़ना विफल हो सकता है - अनुमति त्रुटियां हो सकती हैं, नेटवर्क फ़ाइल सिस्टम के लिए नेटवर्क समस्याएं, डिवाइस त्रुटियां हो सकती हैं यदि फ़ाइल नियमित फ़ाइल नहीं है, आदि। दूसरा, कोई अन्य व्यक्ति आपके द्वारा फ़ाइल के अस्तित्व की जाँच करने और उसे पढ़ने के प्रयास के बीच के समय के बीच हटा कर सकता है। फ़ाइलों से निपटने का प्रयास करते समय सामान्य सलाह यह है कि पहले जाँच करें नहीं। बस फ़ाइल को पढ़ें और catch या Control.Exception के समान या उनके चारों ओर रैपर का उपयोग करके किसी भी अपवाद को पकड़ें

1
dfeuer 2 अगस्त 2019, 19:49