Получить данные типа без сопоставления с образцом для всех конструкторов данных - PullRequest
0 голосов
/ 23 апреля 2020

Есть ли способ сделать абстракцию типа данных и просто использовать значения?

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 или наоборот. Например: определить будущие запасы цветового типа на основе продаж телефонов.

Я хочу понять, в какой степени я могу создавать такие типы, как Цвет, чтобы иметь преимущества использования типа при использовании строки. значение.

Ответы [ 2 ]

10 голосов
/ 23 апреля 2020

Вы могли бы сделать хак, как

{-# 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."

Но я согласен с комментарием Федора Сойкина: почему поле a в каждом конструкторе стоит на первом месте? Просто вычеркни

data Hue = Blue | Green | Red | Yellow | Magenta
data Color a = Color { hue :: Hue, value :: a }
0 голосов
/ 25 апреля 2020

Исходя из ваших правок, похоже, что вы ищете базовый словарь c для работы с Color. Это может быть обеспечено как экземплярами класса, так и функциями специального назначения. Например, экземпляр

A Functor позволяет изменять значение a в Color 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 или с leftaroundabout с одним конструктором . С последним, однако, должно быть легче работать в большинстве ситуаций, поэтому я буду придерживаться его.

  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

Это просто произвольные предложения. Специфика того, что вы хотите определить, будет зависеть от ваших вариантов использования.

...