gpt4 book ai didi

haskell - 将一种类型约束为另一种类型的模式

转载 作者:行者123 更新时间:2023-12-02 11:19:40 27 4
gpt4 key购买 nike

我知道标题不是很好,所以我只想举一个具体的例子。我有一个树状结构,对测试套件进行建模:

data Metadata = Metadata { id :: Id, disabled :: Bool }
data Node =
Suite { metadata :: Metadata, config :: Config, children :: [Node] }
Test { metadata :: Metadata, code :: string }

所以基本上,我们有 Suite s,它们自己可以拥有其他测试 Suite s,或 Test s。这真的很像 Tree定义(带有父 Tree s 和终端 Leaf s)。到目前为止,没有什么太疯狂的,除了我从构造函数中遗漏了其他细节(我为 Config 构造函数使用了一个假设的 Suite 类型,因为它的细节与这个问题无关,除了演示这两个构造函数实际上有很大的不同,所以你不会想要一个直接的递归结构 Node = Node { stuff :: Stuff, children: Maybe [Node] }
现在,我有一个与此类型相关的类型。具体来说,在测试运行时,我会跟踪它们各自的状态:
Status =
Waiting |
Skipped { dueTo :: Id } |
Failure { reason :: Reason } |
Success { duration :: int }
Test s(和 Suite s)在任何给定时刻都可能处于这些状态中的任何一个(由于我认为它们不相关,因此遗漏了更多状态)。 .我将状态存储在来自 Id 的各种散列表中至 Status : Table Id Status .

问题出现了,而 SkippedWaiting实际上对两者都很好 SuiteTest , FailureSuccess实际上想要存储略有不同的数据,具体取决于它们的用途。在不涉及具体信息的情况下,假设我们想要 FailureSuites存储失败的 child Id是为了避免重复重新计算(在我们的例子中存储了实际的非生成数据)。一种选择是将其分成两部分 Status es:
   ...
TestFailure { reason :: Reason } |
SuiteFailure { failedChildren :: [Id] } |
...

但这不是很好,因为您需要类似 isFailure = Status -> Bool 的东西因为有两次失败,而且我们不能保证 TestFailure s 将与 Test 相关联s 在我们的哈希表中。我们可以通过将内部信息拆分为单独的类型来解决第一个问题:
data FailureInfo =
TestInfo { reason :: Reason } |
SuiteInfo { failedChildren :: [Id], otherStuff :: Whatever }

data Status =
...
Failure { info :: FailureInfo }
...

这当然更好,但仍然存在我无法保证 Failure { TestInfo } 的问题。仅与 Test 相关联.这是我的问题的症结所在:给定一个具有多个构造函数的类型,如何以一种我从编译器获得最大支持的方式在这些构造函数上改变支持类型。

如果你暂时想象 SuiteTest实际上是不同的类型(而不仅仅是一种类型的构造函数),我可能想要一个类型参数 Status a ,以及来自 a 的哈希表映射至 Status a (但这也不能完全回答问题)。

最佳答案

如果您只有一个哈希映射,则很难静态地保证测试不会映射到套件失败,反之亦然。
除非您想拥有两种不同的 ID 类型并要求每次查找都指定是否正在查询测试或套件的状态,否则您已经拥有的想法几乎是您可以做的。

如果我可以建议一个更彻底的改变:如何摆脱哈希表并将测试和状态存储在同一结构中?

就像是:

-- s is suite data, t is test data
data Node s t =
Suite { metadata :: Metadata, children :: [Node s t], suiteStuff :: s }
Test { metadata :: Metadata, testStuff :: t }

Status f =
Waiting |
Skipped { dueTo :: Id } |
Failure { failStuff :: f } |
Success { duration :: int }

-- Like the old node type, containing test cases
type TestTree = Node Config String

-- A status tree contains IO actions for retrieving the current status of tests/testsuites
type StatusTree = Node (IO (Status [Id])) (IO (Status Reason))

-- Running tests
startRunning :: TestTree -> IO StatusTree

根据您通常如何遍历状态,这可能会很好地工作。当然,如果您愿意(例如 Table Id (Status (Either [ID] Reason)) ),您仍然可以在其下方拥有一个 HashMap(或两个哈希图),并且树中的 IO 操作只是查找。或者你可以只拥有一个 IORef对于每个套件/测试。

编写或导出 Functor Node 的实例可能非常有用。

关于haskell - 将一种类型约束为另一种类型的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52583315/

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