我在某个数据结构的两种实现之间感到困惑,并且感谢 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 ()
并处理临时多态性(函数专业化等)的含义。
data ServerCenter1 = Server1 | Server2 | Server3
从好的方面来说, typeclass方法易于扩展,将模式匹配分解成更小的块,允许更大的抽象,例如分组服务器(声明 getUrl,您至少在创建实例时被迫做出该决定。
所以,我很伤心,但倾向于将实例作为一种更好的做事方式。有没有一种标准的方法来处理这个问题,或者它是一种“看起来很干净”的东西?