简体   繁体   English

Haskell:编码通用模式

[英]Haskell: encoding a generic schema

To begin with, some motivation: I want to take configuration from multiple places - command line arguments, possibly config files, some other service. 首先,有一些动机:我想从多个地方进行配置-命令行参数,可能是配置文件,以及其他一些服务。 I don't have any particular care for the format of these sources. 我对这些来源的格式没有特别的关心。 What I would like to do is describe a schema for that configuration and have pluggable sources generate parsers/writers for that config as necessary. 我想做的是描述该配置的架构,并根据需要让可插拔源为该配置生成解析器/编写器。 The schema should also encode things such as help text, possibly completion options, etc. 模式还应该对诸如帮助文本,可能的完成选项等进行编码。

Here's the basis of what I have so far: 这是我到目前为止所拥有的基础:

data Name =
    LongName String
  | ShortName Char

data OptionDefault a = OptionDefault (Maybe a) (Maybe (a -> String))

data OptionDescr = OptionDescr {
    odNames :: [Name]
  , odSummary :: String
  , odDetail :: String
}

data Option a = Option {
    oReader :: Monad m => String -> m a
  , oDefault :: OptionDefault a
  , oDescr :: OptionDescr
}

The thing I'm not sure how to do is compose these - eg to define a config section as being, say, three options of types Option Foo , Option Bar and Option Baz as well as a function f :: Foo -> Bar -> Baz -> FBBSection . 我不知道该怎么做是由这些组成的 -例如,将配置节定义为类型为Option FooOption BarOption Baz三个选项以及函数f :: Foo -> Bar -> Baz -> FBBSection This is a different question to composing the Parsers , which should be done at a later date by a generator for the specific format. 这与构成解析器是一个不同的问题, 解析器应在以后由特定格式的生成器来完成。

The only thing I can think of is to store the options as some kind of HList, and force some kind of fold composition for f - any other ideas? 我唯一能想到的就是将选项存储为某种HList,并为f强制进行某种折叠构成-还有其他想法吗?

If you have an Applicative instance for Option: 如果您有Option的适用实例:

foo :: Option Foo
bar :: Option Bar
baz :: Option Baz
f :: Foo -> Bar -> Baz -> FBBSection

fbbSection :: Option FBBSection
fbbSection = f <$> foo <*> bar <*> baz

Now, the trouble is in writing the Applicative instance. 现在,麻烦在于编写Applicative实例。 First of all, you need a Functor instance, but you can't really provide one: OptionDefault is an invariant functor because its type parameter a occurs in both a positive position Maybe a and in a negative position Maybe (a -> String) . 首先,您需要一个Functor实例,但您实际上不能提供一个实例: OptionDefault是不变函子,因为它的类型参数a出现在Maybe a正位置和Maybe a的负位置Maybe (a -> String) OptionDefault Maybe (a -> String) The Functor typeclass in Haskell is only for covariant functors. Haskell中的Functor类型类仅适用于协变函子。

You might re-examine your data to see if you can make it covariant. 您可能需要重新检查数据以查看是否可以使其协变。 There might be an equivalent for Applicative that is invariant though I'm not sure; 尽管我不确定,但Applicative 可能有一个不变的东西。 I'm not sure how currying works for isomorphisms, if it does at all, and Applicative is actually rather dependent on currying, from a categorical perspective. 我不确定curry如何用于同构,如果有的话,从分类的角度来看, Applicative实际上实际上更依赖于currying。

After you got though all of that, you'd need to define how your Applicative combined OptionDescr values. 完成所有这些操作后,您需要定义Applicative如何组合OptionDescr值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM