【发布时间】:2010-11-23 17:42:48
【问题描述】:
我希望你能帮助我。经过多年的命令式语言,我是 Haskell 菜鸟,所以如果我犯了一个愚蠢的错误,请解释一下,以便我学习。
我有以下数据类型:
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 ()
如果我注释掉标记的行,那么代码会编译,但它每次都会加载文件,因为它总是遇到 Nothing。如果我取消注释,我会收到以下错误:
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 转换为可变变量的尝试也失败了:(
干杯
詹姆斯
【问题讨论】:
-
以后请将您的代码缩进四个空格或使用代码按钮(带有 1 和 0 的那个),以便您的代码格式正确。
-
Ack :( AdBlock 对我隐藏了很多界面。我希望已修复。