2

我想指定一个自定义数据类型,如下所示:

data Colour = Red | Green | Blue deriving (Show, Eq, Enum)
data Geometry = Star | Square deriving (Show, Eq, Enum)
data Shape = Shp {colour :: Colour, geom :: Geometry} deriving (Show, Eq, Enum)

现在,如果我不需要始终指定颜色怎么办。这是正确的方法吗?

data Shape = Shp {colour :: Maybe Colour, geom :: Geometry} deriving (Show, Eq, Enum)

这是应该在 Haskell 中完成的方式吗?有没有其他选择,以及这样做的缺点?到目前为止,东西编译了,但我处于学习曲线的开始,只找到一个用过的地方,没有任何说明后续函数如何处理这种情况。

例如,通过颜色等访问值,以及 Show 函数最终会得到很多“Just Red”等。

4

2 回答 2

3

我几乎只写了一个字回复“是”,然后点击提交。你写的完全正确。

与大多数语言一样,还有许多其他方法可以做到这一点,但这确实是“惯用的”方式(您必须学习这个词才能与 Haskell 人群交流:))。例如,第二种较差的方法是将 Color 扩展为包含NoColour...。但这不是一个干净的数据类型,并且生成的类型不太可重用(即,只有颜色的类型可以使用 Maybe 轻松扩展,但是如果你需要,一个类型NoColour不能是非扩展的)。

不过要警告一句:

如果你使用 wrap something in Maybe,Either等,你会发现你的代码在短期内会变得复杂,因为即使是简单的函数也需要考虑JustNothing情况,以及你的颜色。通常你可能会开始有一个阶梯式的语句来处理这些情况......解决这个问题是你真正开始学习 Haskell(monads 等)的时候,然后你的代码将很快开始变得优秀。

(我不敢相信你让我在整篇文章中都像这样拼颜色:))。

于 2014-11-05T17:27:23.463 回答
1

扩展@carsten-könig 的答案,使用 GADT 可以静态地确保仅当静态已知颜色存在时才会使用某些功能,而其他功能可以在所有形状上通用定义。

{-# LANGUAGE GADTs #-}

module Shapes where

data Colour = Red | Green | Blue deriving (Show, Eq, Enum)
data Geometry = Star | Square deriving (Show, Eq, Enum)

我们引入了两种类型,它们的构造函数我们不关心,但 Haskell 可以区分它们。

data Filled
data Blank

我们现在添加一个类型参数到Shape. 根据是否将 aColour分配给形状,我们的Shape构造函数的返回类型会有所不同。

data Shape a where
  Coloured   :: Colour -> Geometry -> Shape Filled
  UnColoured :: Geometry           -> Shape Blank

我们现在可以编写保色函数,例如将 aShape转换为正方形:

toSquare :: Shape a -> Shape a
toSquare (Coloured col _) = Coloured col Square
toSquare (UnColoured _)   = UnColoured Square

或者我们可以仅在对其进行此操作有意义的子集上定义一个函数:safeSetColour该函数是否拒绝覆盖先前分配的颜色,而getColour该函数是否仅在具有颜色Shape的 s 上工作并提取它。

safeSetColour :: Shape Blank -> Colour -> Shape Filled
safeSetColour (UnColoured g) col = Coloured col g

getColour :: Shape Filled -> Colour
getColour (Coloured col _) = col

现在,只有当您需要静态确保 Shape 是or时, Eithermonad 才会出现:FilledBlank

decide :: Shape a -> Either (Shape Filled) (Shape Blank)
decide s@(Coloured _ _) = Left s
decide s@(UnColoured _) = Right s
于 2014-11-06T11:56:47.863 回答