gpt4 book ai didi

haskell - ADT 与类型类——规范使用

转载 作者:行者123 更新时间:2023-12-03 15:09:21 24 4
gpt4 key购买 nike

我在某个数据结构的两种实现之间感到困惑,并且感谢 Haskell 社区关于什么是正确/标准的输入。

数据类型

以 ADT“服务器”为例,它将多个服务器定义为空数据构造函数。

data Server = Server1
| Server2
| Server3

现在,对于这些服务器中的每一个,我都希望(除其他外)能够获取 IP 地址。假设我可以静态编码这些,我可以有一些函数“getURL”和模式匹配。
getUrl :: Server -> String
getUrl Server1 = "192.168.1.1"

等等。现在任何使用服务器的函数都可以将 Server 放入类型中并调用 getURL。
serverStuff :: Server -> IO ()

这种方法似乎具有简单的非多态函数的好处,但代价是在 getURL 中有大量的模式匹配。此外,如果程序员添加了一个服务器但忘记将模式添加到 getURL,他们将在没有警告的情况下收到运行时错误,除非他们使用 -Wall 进行编译。

类型类

针对类型类的相同问题,我可以将我的多构造函数 ADT 分解为一组特定于服务器的 ADT,并为 URL 创建一个类型类。
data Server1 = Server1
data Server2 = Server2
data Server3 = Server3

class Server a where
getUrl :: a -> String

instance Server Server1 where
getUrl Server1 = "192.168.1.1"

等等。现在,我必须创建类似的东西,而不是我之前使用的简单的非多态函数
serverStuff :: Server a => a -> IO ()

并处理临时多态性(函数特化等)的含义。

从好的方面来说,typeclass 方法易于扩展,将模式匹配分解成更小的 block ,允许更大的抽象,例如分组服务器( data ServerCenter1 = Server1 | Server2 | Server3 ),并且,如果您不声明 getUrl,您仍然可能会遇到运行时错误(没有编译器警告),但您至少在创建实例时被迫做出该决定。

所以,我很伤心,但倾向于将实例作为一种更好的做事方式。有没有一种标准的方法来处理这个问题,或者它是一种“看起来很干净”的东西?

最佳答案

如果您确定需要您的服务器类型包含的唯一信息,我会将它们实现为围绕字符串的新类型:

newtype Server = Server { getURL :: String }

使其成为完整记录(如 hammar 的评论)将允许您在仅更改构造函数的同时添加信息,但会牺牲 GeneralizedNewtypeDeriving。

一般来说,我会使用类型来表示事物的类和变量来表示细节,因此空构造函数仅用于表示抽象,例如 data Status = Published | Draft (或内置的 bool )。除非有特定原因,否则应避免将数据(例如 IP 地址)硬编码到类型系统或函数中。

如果您想要特定于服务器的行为,很容易将字段添加到记录中:
data Server = Server {
getURL :: String
, doSomething :: a -> IO () --Or any other functional signature
}

但是,我建议不要这样做,因为它会使其他代码变得晦涩难懂:
runSomething :: Server -> a -> IO ()
runSomething server arg = (doSomething server) arg

绝对可以做任何事情,并且您需要找到该字段的最后更新以确定什么(因为函数没有 Show 实例)。如果依赖项依赖于服务器的某些属性,我会倾向于对该属性进行编码,然后对其进行调度,例如
data ServerType = Production
| Development

data Server = Server {
getURL :: String
, serverType :: ServerType
}

runSomething :: Server -> a -> IO ()
runSomething server arg = case serverType server of
Production -> foo arg
Development -> bar arg

我认为这种方法优于将服务器名称硬编码到函数中,因为它解释了为什么给定服务器具有给定行为(并使特定服务器的行为更本地化),并且在记录字段中具有函数,因为它使更容易判断给定的 runSomething 调用会做什么(因为可以检查和记录 ServerType)。

关于haskell - ADT 与类型类——规范使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13610164/

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