我可以想到三种方法来将几何点定义为Haskell中的代数数据类型。我想将其定义为代数数据类型以获得更好的文档。
作为元组类型:
data Point a = Point a a
作为一个元组:
data Point a= Point (a,a)
作为记录:
data Point a = Point { pointx :: a, pointy :: a}
哪种设计/款式更好?为什么?
答案 0 :(得分:5)
我认为这主要取决于您的用例。
虽然我从不使用数据Point = Point (a, a)
,因为这会引入一层间接,这会使数据结构膨胀 - 由两个机器字组成 - 一个用于Point
,一个用于指针指向里面的元组。
更好地使用type Point a = (a,a)
这只是一个别名或newtype Point a = Point (a,a)
,它在编译时得到优化,因此在这种情况下您可以获益。
最灵活(对于灵活的某些定义)是最后一种方法,但我会将记录pr1
和pr2
调用到第一个/第二个组件& #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
以及镜片的所有细节。
就在最近,我找到了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)
据我所知,更难的是元组,因为很难在元组中创造任何变化。最好的是最后一个。