gpt4 book ai didi

haskell - 在类和记录之间进行选择

转载 作者:行者123 更新时间:2023-12-02 08:13:58 26 4
gpt4 key购买 nike

基本问题:在使用类或使用记录(具有多态字段)之间进行选择时应遵循什么设计原则?

首先,我们知道类和记录本质上是等价的(因为在 Core 中,类被脱糖为字典,而字典只是记录)。然而,还是有区别的:类是隐式传递的,记录必须是显式的。

再深入一点,类在以下情况下非常有用:

  1. 我们对“同一件事”有许多不同的表示,并且
  2. 在实际使用中,可以推断出使用的是哪种表示形式。

当我们(直到参数多态性)只有一种数据表示形式,但我们有多个实例时,类会很尴尬。如果我们不想打开,这会导致必须使用 newtype 添加额外标签(这些标签仅存在于我们的代码中,因为我们知道这些标签在运行时会被删除)的语法噪音各种麻烦的扩展(即重叠和/或不可判定的实例)。

当然,事情会变得更加困惑:如果我想对我的类型进行限制怎么办?让我们举一个真实的例子:

class (Bounded i, Enum i) => Partition a i where
index :: a -> i

我也可以轻松做到

data Partition a i = Partition { index :: a -> i}

但现在我失去了约束,我必须将它们添加到特定的函数中。

是否有设计指南可以帮助我?

最佳答案

我倾向于认为只需要对功能进行限制没有问题。我认为问题是您的数据结构不再精确地模拟您想要的内容。另一方面,如果您首先将其视为一种数据结构,那么这就不那么重要了。

我觉得我不一定对这个问题有很好的把握,这有点模糊,但我的经验法则往往是类型类是遵守法律(或模型含义)的东西,数据类型是编码一定量信息的东西。

当我们想要以复杂的方式分层行为时,我发现类型类一开始很诱人,但很快就会变得痛苦,切换到字典传递会让事情变得更简单。这就是说,当我们希望实现可互操作时,我们应该回退到统一的字典类型。

<小时/>

这是两个,在具体示例上进行了一些扩展,但仍然只是一些旋转想法......

假设我们想要对实数的概率分布进行建模。我想到了两种自然的表征。

A)类型类驱动

class PDist a where
sample :: a -> Gen -> Double

B) 字典驱动

data PDist = PDist (Gen -> Double)

前者让我们做

data NormalDist = NormalDist Double Double -- mean, var
instance PDist NormalDist where...

data LognormalDist = LognormalDist Double Double
instance PDist LognormalDist where...

后者让我们这样做

mkNormalDist :: Double -> Double -> PDist...
mkLognormalDist :: Double -> Double -> PDist...

在前者中,我们可以这样写

data SumDist a b = SumDist a b
instance (PDist a, PDist b) => PDist (SumDist a b)...

在后者中我们可以简单地写

sumDist :: PDist -> PDist -> PDist

那么有什么权衡呢?类型类驱动让我们指定我们所得到的分布。权衡是我们必须显式地构造一个分布代数,包括它们组合的新类型。数据驱动不允许我们限制给定的分布(或者即使它们格式良好),但作为返回,我们可以做任何我们想做的事情。

此外,我们可以相对容易地编写一个 parseDist::String -> PDist,但是我们必须经历一些焦虑才能为类型类方法做等效的事情。

所以,从某种意义上说,这是另一个层面上的类型化/非类型化静态/动态权衡。不过,我们可以稍微改变一下,并认为类型类以及相关的代数定律指定了概率分布的语义。 PDist 类型确实可以成为 PDist 类型类的实例。同时,我们可以让自己几乎在任何地方都使用 PDist 类型(而不是类型类),同时将其视为更“丰富”地使用类型类所需的实例和数据类型塔的 iso。/p>

事实上,我们甚至可以用类型类函数的术语来定义基本的 PDist 函数。即 mkNormalPDist m v = PDist (sample $ NormalDist m v) 因此,设计空间中有很大的空间可以根据需要在两种表示之间滑动...

关于haskell - 在类和记录之间进行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8106764/

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