我希望你能幫助我。我是一個Haskell noob,經過多年的命令式語言,所以如果我犯了一個愚蠢的錯誤,請解釋它,以便我可以學習。IO Monad中的記錄更新失敗?
我有以下數據類型:
data DicomSopInstance = DicomSopInstance {
sopInstancePath :: String,
sopInstanceUid :: String,
sopInstancePk :: Int64,
seriesFk :: Int64,
sopInstanceFrameCount :: Int32,
sourceDicom :: Maybe EncapDicomObject
}
我構建此類型的實例從一個數據庫查詢的結果。當結果出現在sourceDicom字段中時,不能有任何值,所以我將其設置爲Maybe值。當我嘗試加載EncapDicomObject並用結果更新數據類型時,問題就出現了,所以我不必每次只需要從磁盤加載EncapDicomObject就可以訪問它。
以下是導致問題的代碼。我的目的是測試EncapDicomObject是否已經從磁盤讀取,是否已經加載,然後使用現有的(Just)值,如果沒有(沒有檢測到),然後加載它並將Nothing改爲Just。麻煩的行標有「* *」
showImage :: TextCtrl t -> DicomImage -> IO()
showImage textCtl image = do
let sopInst = sopInstance image
let maybeEncapDicom = sourceDicom sopInst
case maybeEncapDicom of
Just encapDicom -> do
showEncapDicomObject textCtl encapDicom (sopInstancePath sopInst)
return()
Nothing -> do
eitherDicom <- readDicomFile $ sopInstancePath sopInst
case eitherDicom of
Left errorMessage -> do
infoM "Hastur" $ "Error reading DICOM file: " ++
(sopInstancePath sopInst) ++ " - " ++ errorMessage
textCtrlSetValue textCtl $ "*** DICOM: " ++
(sopInstancePath sopInst) ++ " ***\n"
textCtrlAppendText textCtl errorMessage
textCtrlAppendText textCtl "\n*** [End] ***"
textCtrlShowPosition textCtl 0
return()
Right encapDicom -> do
sopInst { sourceDicom = Just encapDicom } -- ****
showEncapDicomObject textCtl encapDicom (sopInstancePath sopInst)
return()
如果我註釋掉標記線,則代碼編譯,但它每次加載,因爲它總是遇到沒有過的文件。如果我取消我收到以下錯誤:
src\Hastur.hs:382:10:
Couldn't match expected type `IO a'
against inferred type `DicomSopInstance'
In a stmt of a 'do' expression:<br>
sopInst {sourceDicom = Just encapDicom}
我將此解釋爲意味着該語句返回DicomSopInstance而不是IO(),但我所有的嘗試創建一個函數來更新sopInst和返回IO()有失敗。
我錯過了什麼?當Haskell的非嚴格行爲會爲我做或者我只是得到錯誤的設計時,我是否試圖按需加載?我嘗試sourceDicom轉換爲可變變量都前功盡棄以及:(
歡呼
詹姆斯
將來,請將您的代碼縮進四個空格或使用代碼按鈕(帶有「1」和「0」的代碼),以便您的代碼格式正確。 – sepp2k 2010-11-23 17:56:44
Ack :(AdBlock隱藏了我的很多界面,修復了我希望的問題 – 2010-11-23 18:15:59