Haskell 使用monads读取INI文件

Haskell 使用monads读取INI文件,haskell,Haskell,我正在尝试使用monads读取haskell的INI文件 这是我的密码: import Control.Monad import Data.Ini main = do config <- readIniFile "configs/config.ini" port <- (config >>= lookupValue "NETWORK" "port") port >>= putStrLn import-Control.Monad 导入

我正在尝试使用monads读取haskell的INI文件

这是我的密码:

import Control.Monad
import Data.Ini

main = do
    config <- readIniFile "configs/config.ini"
    port <- (config >>= lookupValue "NETWORK" "port")
    port >>= putStrLn
import-Control.Monad
导入数据.Ini
main=do
config=lookupValue“网络”“端口”)
端口>>=putStrLn

在我有限的理解中,
config
port
将是一种类型。如何将
值与
IO
操作一起使用

涉及两种不同的单子
readIniFile
返回一个
IO(任意字符串Ini)
值,这意味着
config
具有类型
任意字符串Ini
。在这个
do
表达式中,您不能从
config>>=lookupValue“NETWORK”“port”
返回的
字符串文本
值中提取
文本
值。相反,如果查找失败,请使用
返回默认值,如果查找成功,则提取端口

getPort :: Ini -> Either String Text
getPort cfg = let result = lookupValue "NETWORK" "port" cfg
              in case result of
                    Left "Couldn't find key: port" -> Right "0"
                    otherwise -> result

 main = do
  config <- readIniFile "configs/config.ini"
  -- You could probably do better than just raise an error
  let port = either error id (config >>= getPort)
  putStrLn (unpack port)
getPort::Ini->任意字符串文本
getPort cfg=let result=lookupValue“网络”“端口”cfg
万一结果
左“找不到键:端口”->右“0”
否则->结果
main=do
配置>=getPort)
putStrLn(拆包端口)

由于涉及多个monad,因此可以使用monad转换器。虽然您希望将
monad transformer称为
EitherT
,但出于各种原因,它被称为
ExceptT

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Except
import Data.Ini

main = runExceptT $ do
  config <- ExceptT $ readIniFile "./config.ini"
  port <- ExceptT $ return $ lookupValue "NETWORK" "port" config
  liftIO $ putStrLn $ show port
{-#语言重载字符串}
模块主要在哪里
导入控制.Monad.IO.Class(liftIO)
进口管制.单子交易.例外
导入数据.Ini
main=runExceptT$do

配置您知道如何在不使用
IO
操作的情况下使用
or
值吗?我使用了此处突出显示的
case的
语法尝试了这一点:它似乎有效。现在尝试使用
bind
进行学习。不,这是正确的解决方案。您可以使用
fromRight
函数,但我认为这不是一个显著的改进。请注意,如果有
分支终止程序(出现错误或异常),而右分支返回值,则不需要像这样保持嵌套。您不能使用bind进行此操作:大致上,bind会从其一元上下文中取出一些内容,如果这些内容随后被重新插入到同一个一元上下文中。您不能从
中取出某个内容并使用bind将其放入
IO
。因为这只是忽略了
lookupValue
可能返回的错误消息,所以您也可以使用
fromRight“0”(配置>>=…)
。(我认为这需要导入
数据。要么
要么
没有,但我目前无法确认。)我想知道嵌套的
是否可以
并继续使用
=
,防止它忽略配置读取错误,如果有的话,@9000在引入monad transformers时可能会比当前代码更不清晰。是的,这种情况下的问题是同时做两件事,这对于一个示例来说很好,但在“真实”代码中却不是很好-配置值不存在通常不是错误(除非它确实不存在合理的默认值),但您肯定希望将配置文件中的语法错误视为错误。@bipll
other
不是,但
other String
是。说到“各种原因”,我要补充的是,您可能会看到使用
Error
的较旧代码,它具有虚假的
Error
约束,或者
EitherT
来自(较旧版本的?
other
),但是
ExceptT
是当今
other
变压器的正确选择。