首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Dhall的渐进式打字

Dhall的渐进式打字
EN

Stack Overflow用户
提问于 2022-03-30 11:07:25
回答 1查看 57关注 0票数 2

Dhall网站有一个很好的例子:

代码语言:javascript
复制
{- You can optionally add types

   `x : T` means that `x` has type `T`
-}

let Config : Type =
      {- What happens if you add another field here? -}
      { home : Text
      , privateKey : Text
      , publicKey : Text
      }

let makeUser : Text -> Config = \(user : Text) ->
      let home       : Text   = "/home/${user}"
      let privateKey : Text   = "${home}/.ssh/id_ed25519"
      let publicKey  : Text   = "${privateKey}.pub"
      let config     : Config = { home, privateKey, publicKey }
      in  config

let configs : List Config =
      [ makeUser "bill"
      , makeUser "jane"
      ]

in  configs

就像注释要求我做的那样,我添加了另一个字段:foo : TextConfig类型,而现在这个示例无法进行类型检查。这使我无法逐步向现有项目添加类型。我错过了一个逃生舱口,让我可以逐渐增加知识,因为我变得更加熟悉的动态配置的项目,我不拥有。

我敢打赌,这是一种常见的情况:“我正在维护一个我不拥有的项目,在YAML或JSON中配置,没有模式,或者使用一个松散定义的模式。”

我相信我想要的是所谓的“行多态”,好像已经讨论过了 (并拒绝了?)在Dhall问题上,我有什么办法可以解决同样的问题呢?从我的角度来看,在我没有全部信息的情况下,我似乎不能使用Dhall?

EN

回答 1

Stack Overflow用户

发布于 2022-03-30 23:40:52

您说得对,最符合人体工程学的解决方案将是对行多态性的语言支持。例如,请参阅另一个支持行多态性的概念证明项目:

然而,Dhall确实有一个语言特性,它在这里仍然有帮助,这就是支持按预期类型投影记录的字段。换句话说,如果一个记录r包含Config中字段的超集,那么您就可以使用r.(Config)来投影感兴趣的字段。

通常,我会在您从dhol-lang.org引用的示例的上下文中说明这是如何工作的,但这个特定示例的问题是,它不可能默默地忽略额外foo字段的存在,即使Dhall支持行多态性。这是因为makeUser函数生成一个Config而不是使用一个Config,所以如果您承诺生成额外的字段,那么您必须实际添加预期的字段。

然而,本着您的请求精神,我将使用一个相关的例子,我认为这更接近您的想法。唯一的区别是,我们将把函数更改为消耗Config的函数

代码语言:javascript
复制
let Config : Type = { home : Text, privateKey : Text, publicKey : Text }

let render =
      λ(config : Config) →
        ''
        Home: ${config.home}
        Private Key: ${config.privateKey}
        Public Key: ${config.publicKey}
        ''

let example =
      { home = "/home/gabriella"
      , privateKey = "/home/gabriella/.ssh/id_ed25519"
      , publicKey = "/home/gabriella/.ssh/id_ed25519.pub"
      }

in  render example

我们希望能够在示例中添加另一个foo字段,但不破坏render函数。换句话说,我们希望render函数无声地忽略Config类型中的字段以外的任何字段。

通常,在具有行多态性的语言中,您可以通过将render的类型更改为如下所示来解决这个问题:

代码语言:javascript
复制
let render =
      λ(config : { home : Text, privateKey : Text, privateKey : Text | r }) →
        ''
        Home: ${config.home}
        Private Key: ${config.privateKey}
        Public Key: ${config.publicKey}
        ''

let example =
      { home = "/home/gabriella"
      , privateKey = "/home/gabriella/.ssh/id_ed25519"
      , publicKey = "/home/gabriella/.ssh/id_ed25519.pub"
      , foo = "bar"
      }

in  render example

…其中,rrender类型中表示“我们希望忽略的其他字段”。正如您所指出的,Dhall不支持这种方法,但是如果我们使用Dhall对按类型投影字段的支持,我们可以这样做:

代码语言:javascript
复制
let Config : Type = { home : Text, privateKey : Text, publicKey : Text }

let render =
      λ(config : Config) →
        ''
        Home: ${config.home}
        Private Key: ${config.privateKey}
        Public Key: ${config.publicKey}
        ''

let example =
      { home = "/home/gabriella"
      , privateKey = "/home/gabriella/.ssh/id_ed25519"
      , publicKey = "/home/gabriella/.ssh/id_ed25519.pub"
      , foo = "bar"
      }

in  render example.(Config)

它不像行多态那样符合人体工程学,但至少它解决了代码对添加新字段的上游输入中的更改不敏感的用例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71676112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档