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

jar*_*ond 4 haskell

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

作为元组类型:

data Point a = Point a a
Run Code Online (Sandbox Code Playgroud)

作为一个元组:

data Point a= Point (a,a)
Run Code Online (Sandbox Code Playgroud)

作为记录:

data Point a = Point { pointx :: a, pointy :: a}
Run Code Online (Sandbox Code Playgroud)

哪个更好的设计/风格,为什么?

eps*_*lbe 5

我认为这主要取决于您手头的用例.

虽然我从不使用数据Point = Point (a, a),因为这引入了一层间接,它使数据结构膨胀 - 由两个机器字 - 一个用于Point指针和指向其中元组的指针.

更好地使用type Point a = (a,a)它只是一个别名或newtype Point a = Point (a,a)在编译时得到优化,所以你在这种情况下有好处.

最灵活的(对于一些灵活的定义)是最后一种方法,尽管我会调用记录pr1并将pr2"投影到第一个/第二个组件".这种方法也非常适合使用镜头.

正如@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)
Run Code Online (Sandbox Code Playgroud)

它可以让你使用的好处norm Point{..} = sqrt (_pr1^2 + _pr2^2)RecordWildCards和镜头上的细微区别.

更新(2017-09-03):

就在最近,我发现了严格的包,它提供了严格的数据集以及严格的IO操作.向我伸出的一件事是来自Data.Strict.Maybe的以下内容

请注意,严格的Maybe不是monad,因为return ? >>= f = ?它不一定是相同的f ?.

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

  • "`类型Point a =(a,a)`它只是一个别名或`newtype Point a = Point(a,a)`"仅在操作上为真:在类型级别,只有后者会让编译器帮助你区分点和元组,并允许你为`Point`添加新实例. (2认同)