Jac*_*tte 33 haskell record typeclass
基本问题:在选择使用类或使用记录(具有多态字段)时,应该遵循哪些设计原则?
首先,我们知道类和记录本质上是等价的(因为在Core中,类被去掉了字典,这只是记录).然而,存在差异:类是隐式传递的,记录必须是显式的.
更深入一点,在以下情况下,课程非常有用:
当我们(仅参数多态)只有一个数据表示时,类很尴尬,但我们有多个实例.如果我们不想打开各种麻烦的扩展(即,我们知道这些标记在运行时被删除),这导致了必须使用newtype添加额外标记(仅存在于我们的代码中,因为我们知道此类标记在运行时被删除)的语法噪音(即重叠和/或不可判定的实例).
当然,事情变得更加混乱:如果我想对我的类型有限制怎么办?让我们选一个真实的例子:
class (Bounded i, Enum i) => Partition a i where
index :: a -> i
Run Code Online (Sandbox Code Playgroud)
我可以很容易地完成
data Partition a i = Partition { index :: a -> i}
Run Code Online (Sandbox Code Playgroud)
但现在我已经失去了约束,我将不得不将它们添加到特定的功能中.
是否有设计指南可以帮助我?
我倾向于看到只需要对函数进行约束的问题.我想问题是,您的数据结构不再精确地模拟您的意图.另一方面,如果您首先将其视为数据结构,那么这应该更少.
我觉得我不一定能很好地掌握这个问题,而且这个问题虽然模糊不清,但我的经验法则往往是类词类是遵守法则(或模型意义)和数据类型的东西.是编码一定数量信息的东西.
当我们想要以复杂的方式对行为进行分层时,我发现类型类很容易开始,但是很快就会变得很痛苦并且切换到字典传递会使事情变得更加简单.也就是说,当我们希望实现可以互操作时,我们应该回归到统一的字典类型.
这需要两个,在一个具体的例子上扩展一点,但仍然只是一些旋转的想法......
假设我们想要对实数的概率分布进行建模.我想到了两种自然的表征.
A)类型驱动
class PDist a where
sample :: a -> Gen -> Double
Run Code Online (Sandbox Code Playgroud)
B)字典驱动
data PDist = PDist (Gen -> Double)
Run Code Online (Sandbox Code Playgroud)
前者让我们这样做
data NormalDist = NormalDist Double Double -- mean, var
instance PDist NormalDist where...
data LognormalDist = LognormalDist Double Double
instance PDist LognormalDist where...
Run Code Online (Sandbox Code Playgroud)
后者让我们这样做
mkNormalDist :: Double -> Double -> PDist...
mkLognormalDist :: Double -> Double -> PDist...
Run Code Online (Sandbox Code Playgroud)
在前者,我们可以写
data SumDist a b = SumDist a b
instance (PDist a, PDist b) => PDist (SumDist a b)...
Run Code Online (Sandbox Code Playgroud)
在后者我们可以简单地写
sumDist :: PDist -> PDist -> PDist
Run Code Online (Sandbox Code Playgroud)
那么有什么权衡?类型类驱动让我们指定我们给出的分布.权衡是我们必须明确地构建分布的代数,包括它们组合的新类型.数据驱动不会让我们限制我们给出的分布(或者即使它们格式正确),但作为回报,我们可以做任何我们想要的事情.
此外,我们可以parseDist :: String -> PDist
相对容易地编写,但我们必须经历一些焦虑来为类型类方法做等效.
从某种意义上说,这是另一个级别的类型化/非类型化静态/动态权衡.我们可以给它一个转折,并且认为类型类以及相关的代数定律指定了概率分布的语义.并且PDist类型确实可以成为PDist类型类的实例.同时,我们可以听任使用PDist类型(而不是类型类)几乎无处不在,而想着它作为ISO必要使用类型类多个实例和数据类型的塔"丰富".
实际上,我们甚至可以根据类型类函数定义基本的PDist 函数.即mkNormalPDist m v = PDist (sample $ NormalDist m v)
所以在设计空间中有很多空间可以根据需要在两个表示之间滑动......
归档时间: |
|
查看次数: |
842 次 |
最近记录: |