几何点数据类型 - 元组vs记录?

时间:2016-01-31 09:54:14

标签: haskell

我可以想到三种方法来将几何点定义为Haskell中的代数数据类型。我想将其定义为代数数据类型以获得更好的文档。

作为元组类型:

data Point a = Point a a

作为一个元组:

data Point a= Point (a,a)

作为记录:

data Point a = Point { pointx :: a, pointy :: a}

哪种设计/款式更好?为什么?

3 个答案:

答案 0 :(得分:5)

我认为这主要取决于您的用例。

虽然我从不使用数据Point = Point (a, a),因为这会引入一层间接,这会使数据结构膨胀 - 由两个机器字组成 - 一个用于Point,一个用于指针指向里面的元组。

更好地使用type Point a = (a,a)这只是一个别名或newtype Point a = Point (a,a),它在编译时得到优化,因此在这种情况下您可以获益。

最灵活(对于灵活的某些定义)是最后一种方法,但我会将记录pr1pr2调用到第一个/第二个组件& #39 ;.这种方法也非常适合使用镜头。

正如@nikitavolkov所说 - 出于性能原因,拥有严格的数据字段是一个好主意,但正如我喜欢的记录一样,我最终会选择

{-# LANGUAGE TemplateHaskell -#}
{-# LANGUAGE DeriveFoldable -#}
{-# LANGUAGE DeriveFunctor -#}
{-# LANGUAGE DeriveTraversable -#}
{-# LANGUAGE RecordWildCards #-}

import Control.Lens

data Point a = Point { _pr1 :: !a
                     , _pr2 :: !a
                     } deriving (..)
$(makeLenses ''Point)

可以让您norm Point{..} = sqrt (_pr1^2 + _pr2^2)使用RecordWildCards以及镜片的所有细节。

更新(2017-09-03):

就在最近,我找到了strict package,它提供了严格的数据集以及严格的IO操作。从我Data.Strict.Maybe

中可以看到以下一点:
  

请注意,严格的Maybe不是return ⊥ >>= f = ⊥以后的monad,它不一定与f ⊥相同。

我认为这也适用于严格的对 - 所以在定义和/或使用严格的数据类型时请记住这一点。

答案 1 :(得分:4)

记录在Haskell中是一个有争议的主题。社群已达成共识,由于许多原因,现有的实施工作并不理想,而且正在采取措施解决这个问题。

现在,由于现有的记录实现不是最理想的,因此许多Haskeller都不会使用它们。我是其中之一。

我建议使用以下内容:

{-# LANGUAGE DeriveFoldable, DeriveFunctor, DeriveTraversable #-}

data Point a =
  Point !a !a
  deriving (Functor, Foldable, Traversable)

这将为您提供一些标准类的自由实例,并且建议使用严格的数据结构。

答案 2 :(得分:-2)

据我所知,更难的是元组,因为很难在元组中创造任何变化。最好的是最后一个。