处理Haskell中第三方库的数据类型的最佳实践?

时间:2015-06-15 20:25:03

标签: haskell types

我刚刚进入我的第一个真正的Haskell大小项目(一个Web应用程序),我开始遇到第三方库中的类型泄露我的代码的问题。这是一个简单的例子:

我的Parser模块导入Test.Parsec,并导出返回parseConfig的函数(Either ParseError DbConfig),其中ParseError是在此定义的数据类型Parsec库(DbConfig是我的应用的自定义数据类型,为简洁起见未显示。)

-- Parser.hs
module Parser where

import Text.Parsec

parseConfig :: String -> Either ParseError DbConfig
parseConfig = parse ...

稍后,我想使用我的parseConfig功能,但为了使用它,我必须再次导入Text.Parsec,以便我可以访问ParseError类型。

-- Api.hs
module Api where

import Parser
import Text.Parsec

getConfigFromBody :: Object -> Either ParseError DbConfig
getConfigFromBody = parseConfig . (...)

这不仅是管理进口的麻烦,而且是关注点的差异分离,因此我知道这不是最好的方法。我的问题是,管理这个问题的最佳做法是什么?制作类型同义词是否理想?

type ConfigParseError = ParseError

parseConfig :: String -> Either ConfigParseError DbConfig
parseConfig = parse ...

这似乎是合理的,因为将Parsec依赖项保留在我的Parser模块内部,但是别名库类型似乎是默认使用的奇怪模式。

所以我的问题是,较大的Haskell应用程序或库如何处理这个问题?是否有从第三方库管理数据类型的通用技术?

1 个答案:

答案 0 :(得分:7)

我还没有准备好提供一份很好的最佳实践清单,但对于初学者来说,如果你想保持井井有条的组织,请使用显式导出而不是仅导出所有内容,例如:

module Parser
  ( parseConfig
  ) where
...

显式导出还允许您重新导出导入,例如

module Parser
  ( parseConfig
  , ParseError(..)
  ) where
...

之后,您可以import Parser,并ParseError可用,就像在Parser内定义一样。

我认为这应该可以解决你当前的问题。