Я надеюсь, что вы можете мне помочь. Я новичок в Haskell после многих лет императивных языков, поэтому, если я делаю глупую ошибку, объясните ее, чтобы я мог учиться.
У меня есть следующий тип данных:
data DicomSopInstance = DicomSopInstance {
sopInstancePath :: String,
sopInstanceUid :: String,
sopInstancePk :: Int64,
seriesFk :: Int64,
sopInstanceFrameCount :: Int32,
sourceDicom :: Maybe EncapDicomObject
}
Я создаю экземпляры этого типа из результатов запроса к базе данных. Когда результаты приходят в поле sourceDicom, оно не может иметь никакого значения, поэтому я сделал его значением «Может быть». Проблема возникает, когда я пытаюсь загрузить EncapDicomObject и обновить тип данных с результатом, поэтому мне не нужно загружать EncapDicomObject с диска каждый раз, когда я хочу получить к нему доступ.
Ниже приведен код, вызывающий проблему. Мое намерение состоит в том, чтобы проверить, был ли EncapDicomObject прочитан с диска, если он был загружен, используйте существующее (просто) значение, если нет (ничего не обнаружено), затем загрузите его и измените ничего на просто. Проблемная строка отмечена "**"
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}
Я интерпретирую это как означающее, что stmt возвращает DicomSopInstance вместо IO(), но все мои попытки создать функцию для обновления sopInst и возврата IO() не увенчались успехом.
Что мне не хватает? Пытаюсь ли я выполнить загрузку по требованию, когда нестрогое поведение Haskell сделает это за меня, или у меня просто неправильный дизайн? Мои попытки преобразовать sourceDicom в изменяемую переменную также ни к чему не привели :(
ваше здоровье
Джеймс
return (image {sopInstance = newSopInst})
и присвойте вашей функции типshowImage :: TextCtrl t -> DicomImage -> IO DicomImage
. Вы всегда можете схитрить и использовать настоящее изменяемое состояние с MVar/IORef, но гораздо лучше заранее освоить правильный путь и использовать MVars/IORefs только тогда, когда это действительно необходимо (как правило, либо с параллелизмом, либо с некоторыми забавными типами ffi). ). 24.11.2010