如何管理简单配置

时间:2015-07-24 10:07:08

标签: haskell

我的应用程序需要一个非常简单的配置,由应用程序启动时初始化的basePath组成,这样:

data Conf = Conf {
    basePath :: FilePath
    genericValue :: Int
}

startApp :: IO ()
startApp = do
  hd <- getHomeDirectory
  let conf = conf (basePath = hd ++ "/some_dir/", genericValue = 10)
  -- start to pass around conf

要获取我刚才使用的值:basePath confgenericValue conf

有没有更好的方法来管理这个并且可能避免在函数中传递这个conf值?在我身边,我可以找到像Read Monad这样的建议,但我看不到真正的优势。

1 个答案:

答案 0 :(得分:1)

就像@Carsten所说,Reader monad的优点是你可以避免必须通过conf!而不是写:

data Conf = Conf {
    basePath :: FilePath
    genericValue :: Int
}

somethingSimple :: Conf -> Foo
somethingSimple conf = ...

somethingElse :: Conf -> Bar
somethingElse conf = ...

somethingComplex :: Conf -> (Foo, Bar)
somethingComplex conf = (somethingSimple conf, somethingElse conf)

你写道:

somethingSimple :: Reader Conf Foo
somethingSimple = do
  conf <- ask
  return ...

somethingElse :: Reader Conf Bar
somethingElse conf = do
  conf <- ask
  return ...

somethingComplex :: Reader Conf (Foo, Bar)
somethingComplex = do
  a <- somethingSimple
  b <- somethingElse
  return (a, b)

从而完全消除conf somethingComplex定义中的Conf:您只需通过组合其他内容来定义一个读取某些 Conf值的操作读取某些 Conf值的操作。您只能传递一次实际的runReader,即somethingComplex' :: Reader Conf (Foo, Bar) somethingComplex' = liftM2 (,) somethingSimple somethingElse

另外,你可以写下很酷的东西:

var query =    
from c in Customers    
where !(from n in npConsultant
    where n.ConsultantName='X'    
        select n.Code)    
       .Contains(c.Code)    
    && c.Code < 'AA.0000'
select c.Code, c.Name;