gpt4 book ai didi

Haskell - 任何方式来限定或消除记录名称的歧义?

转载 作者:行者123 更新时间:2023-12-03 21:18:19 27 4
gpt4 key购买 nike

我有两种数据类型,用于 mustache 模板。在我的代码中,有两种不同的类型是有意义的,它们都有一个名为“name”的字段。这当然会引起冲突。似乎有一种机制可以消除对“名称”的任何调用,但实际定义会导致问题。是否有任何解决方法,比如让记录字段名称被限定?

data DeviceArray = DeviceArray
{ name :: String,
bytes :: Int }
deriving (Eq, Show, Data, Typeable)

data TemplateParams = TemplateParams
{ arrays :: [DeviceArray],
input :: DeviceArray }
deriving (Eq, Show, Data, Typeable)

data MakefileParams = MakefileParams
{ name :: String }
deriving (Eq, Show, Data, Typeable)

即,如果这些字段现在在代码中使用,它们将是“DeviceArray.name”和“MakefileParams.name”?

最佳答案

如前所述,这不是直接可能的,但我想对提议的解决方案说几件事:

如果这两个字段明显不同,那么您总是想知道您正在使用哪个字段。这里的“明显不同”是指永远不会有对任何一个领域做同样的事情是有意义的情况。鉴于此,过度消歧并不是不受欢迎的,因此您希望将合格的导入作为标准方法,或者如果这更符合您的口味,则需要字段消歧扩展。或者,作为一个非常简单(而且有点难看)的选项,只需手动为字段添加前缀,例如deviceArrayName而不仅仅是 name .

如果这两个领域在某种意义上是同一个东西,那么能够以同质的方式对待它们是有意义的;理想情况下,您可以编写一个多态函数来选择 name field 。在这种情况下,一种选择是为“命名事物”使用类型类,其函数允许您访问 name任何适当类型的字段。这里的一个主要缺点是,除了琐碎的类型约束的扩散和可怕的单态限制可能令人头疼的问题之外,您还失去了使用记录语法的能力,这开始破坏整个观点。

我还没有看到建议的类似字段的另一个主要选项是提取 name字段输出为单个参数化类型,例如data Named a = Named { name :: String, item :: a } . GHC itself uses this approach for source locations in syntax trees ,虽然它不使用记录语法,但想法是一样的。这里的缺点是,如果您有 Named DeviceArray , 访问 bytes字段现在需要经过两层记录。如果要更新 bytes具有功能的字段,您会遇到以下问题:

addBytes b na = na { item = (item na) { bytes = b + bytes (item na) } }

啊。有一些方法可以稍微缓解这个问题,但在我看来,它们仍然不知道。像这样的情况是我一般不喜欢记录语法的原因。所以,作为最后的选择,一些模板 Haskell 魔法和 the fclabels package :
{-# LANGUAGE TemplateHaskell #-}

import Control.Category
import Data.Record.Label

data Named a = Named
{ _name :: String,
_namedItem :: a }
deriving (Eq, Show, Data, Typeable)

data DeviceArray = DeviceArray { _bytes :: Int }
deriving (Eq, Show, Data, Typeable)

data MakefileParams = MakefileParams { _makefileParams :: [MakeParam] }
deriving (Eq, Show, Data, Typeable)

data MakeParam = MakeParam { paramText :: String }
deriving (Eq, Show, Data, Typeable)

$(mkLabels [''Named, ''DeviceArray, ''MakefileParams, ''MakeParam])

不要介意 MakeParam业务,我只需要在那里做一些事情。无论如何,现在您可以像这样修改字段:
addBytes b = modL (namedItem >>> bytes) (b +)
nubParams = modL (namedItem >>> makefileParams) nub

您也可以命名 bytes类似于 bytesInternal然后导出访问器 bytes = namedItem >>> bytesInternal如果你喜欢。

关于Haskell - 任何方式来限定或消除记录名称的歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6922437/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com