Data.ConfigFile 没有使用 get 的 Bool 实例

Data.ConfigFile not using the Bool instance of get

根据https://hackage.haskell.org/package/ConfigFile-1.0.5/docs/Data-ConfigFile.html,该包将转换配置中的一个值。文件到布尔。以下代码:

{-# LANGUAGE FlexibleContexts #-}


import qualified Data.ConfigFile as DC
import qualified Control.Monad.Except as CME


-- | The foundation object
data JRState = JRState {
        secureOnly :: Bool  -- ^ restrict connections to HTTPS
    }


main :: IO ()
main = (CME.runExceptT $ pipe (JRState False)) >>= estate


estate :: Show t => Either t JRState -> IO ()
estate (Right state) = return ()
estate (Left err) = do
    putStrLn $ "<<" ++ show err ++ ">>"
    return ()


pipe :: (CME.MonadError DC.CPError m, CME.MonadIO m) => JRState -> m JRState
pipe site = do
    cp <- CME.join $ CME.liftIO $ return $ DC.readstring DC.emptyCP{DC.optionxform=id} "secureSession = True\n"
    DC.get cp "DEFAULT" "secureSession" >>= return . nubb where
        nubb (Left err) = error err
        nubb (Right value) = site{secureOnly = value}

当运行时,产生

<<(ParseError "couldn't parse value True from (DEFAULT/secureSession)","genericget")>>

这显然来自 estate 中的 putStrLn。但我希望在 pipe 和 nubb(愚蠢的名字,我知道)中提取值会强制使用布尔上下文,从而强制将 True 字符串转换为 Bool。我试过 1 和是,结果相同。怎么回事?

这是一个具有类似问题行为的更小的程序:

import qualified Data.ConfigFile as DC
import qualified Control.Monad.Except as CME

main = CME.runExceptT pipe >>= print
pipe = do
    cp <- DC.readstring DC.emptyCP{DC.optionxform=id} "secureSession = True\n"
    DC.get cp "DEFAULT" "secureSession" >>= nubb

nubb :: Either String Bool -> m Bool
nubb = undefined

当它被简化为这种基本形式时,很明显出了什么问题:你要求 DC.get 到 return 和 Either String Bool 而实际上你应该只是要求它 return 一个 Bool。精简版的简单修复是完全消除该行的 >>= nubb 部分;应该很容易将此修复程序转换回更大的上下文。