在所有数据构造函数上获取没有模式匹配的类型的数据

Get data of type without pattern match on all data contructors

有没有办法抽象数据类型并只使用值?

data Color a = Blue a | Green a | Red a | Yellow a | Magenta a deriving (Show)

类似于:

calcColor :: Color a -> Color a -> Maybe a
calcColor (_ x) (_ y) = Just $ x + y

不一定要在函数声明中。 我在想的一个选择是 fromJust 之类的东西,但即便如此也感觉有点多余。

fromColor :: Color a -> a
fromColor (Blue t) = t
fromColor (Red t) = t
fromColor (Green t) = t
fromColor (Yellow t) = t

编辑 - 添加上下文和更多说明

从我设法质疑它的方式来看,标题可能看起来像一个重复的问题。

我不太确定,但这是由社区决定的。 我是 Haskell 的新手,所以也许我的问题看起来很愚蠢,但我仍然认为这是一个有效的案例,因为我确实遇到过这种情况。

@FyodorSoikin,@leftaroundabout 你的回答对我有帮助,但部分帮助。我会尝试更好地解释我到底想要实现什么。

我想将颜色类型视为一个类别(假设是 G),颜色是 G 的元素, 我也有不同颜色的手机。电话类别(假设为 H)。

现在我尝试想出一种方法来使用 G 类别的态射(函数),使用 H 类别中的函子或相反的方式。 例如:根据手机的销量来判断某个颜色类型的未来库存。

我想了解我可以在多大程度上创建像 Color 这样的类型来获得类型的优势,而不是使用字符串值。

你可以像这样破解

{-# LANGUAGE DeriveFoldable #-}
import Data.Foldable (Foldable, toList)

data Color a = Blue a | Green a | Red a | Yellow a | Magenta a 
  deriving (Show, Foldable)

fromColor :: Color a -> a
fromColor c = case toList c of
   [ca] -> ca
   _ -> error "Impossible, `Color` has only one field."

但我同意 Fyodor Soikin 的评论:为什么首先在每个构造函数中都有 a 字段?把它分解出来

data Hue = Blue | Green | Red | Yellow | Magenta
data Color a = Color { hue :: Hue, value :: a }

根据您的编辑,您似乎正在寻找处理 Color 的基本词汇。这可以由 class 实例和专用函数提供。

例如,

Functor 实例允许您独立于颜色本身更改 Color a 中的 a 值:

data Hue = Blue | Green | Red | Yellow | Magenta
    deriving (Eq, Show)

data Color a = Color { hue :: Hue, value :: a }
    deriving (Eq, Show)

instance Functor Color where
    fmap f (Color h a) = Color h (f a)
GHCi> test1 = Color Red 27
GHCi> fmap (2*) test1
Color {hue = Red, value = 54}

两个简短的说明:

  1. 我在这里建议的事情同样可以用你的四构造函数 Color 类型或 来完成。不过,后者在大多数情况下应该更容易使用,所以我会坚持使用它。

  2. DeriveFunctor 扩展意味着您几乎不必显式编写 Functor 实例:通过将 {-# LANGUAGE DeriveFunctor #-} 添加到文件顶部来打开它,然后然后写:

    data Color a = Color { hue :: Hue, value :: a }
        deriving (Eq, Show, Functor)
    

您可能想要做的另一件事是拥有一个 Hue -> Colour a -> Maybe a 函数,这将为您提供一种使用 Maybe 上的操作的方法,以根据附加的色调过滤 a 值:

colorToMaybe :: Hue -> Color a -> Maybe a
colorToMaybe chosenHue col
    | hue col == chosenHue = Just (value col)
    | otherwise = Nothing
GHCi> test1 = Color Red 27
GHCi> test2 = Color Red 14
GHCi> test3 = Color Blue 33
GHCi> import Data.Maybe
GHCi> mapMaybe (colorToMaybe Red) [test1, test2, test3]
[27,14]
GHCi> import Control.Applicative
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test2)
Just 41
GHCi> liftA2 (+) (colorToMaybe Red test1) (colorToMaybe Red test3)
Nothing

这些只是相当武断的建议。您要定义的具体内容取决于您的用例。