Подтвердить что ты не робот

Должен ли я использовать класс или нет?

У меня есть некоторые трудности, чтобы понять, когда вы используете и когда не используете typeclass в моем коде. Я имею в виду создать свой собственный, а не использовать уже определенные типы классов, конечно. Например (очень глупый пример), должен ли я делать:

data Cars = Brakes | Wheels | Engine
data Computers = Processor | RAM | HardDrive  

class Repairable a where
    is_reparaible :: a -> Bool

instance Repairable Cars where
    is_repairable (Brakes) = True
    is_repairable (Wheels) = False
    is_repairable (Engine) = False

instance Repairable Computers where
    is_repairable (Processor) = False
    is_repairable (RAM)       = False
    is_repairable (HardDrive) = True

checkState :: (Reparaible a) => a -> ... 
checkState a = ...

(Очевидно, это глупый, неполный пример).

Но это много для небольшого использования, нет? Почему я не должен делать что-то простое и только определяя функции без определения новых типов данных и типов (с их экземплярами).

Этот пример слишком прост, но в фактах я часто вижу подобные вещи (новые типы данных + типы + экземпляры), когда я просматриваю код Haskell на github вместо определения только функций.

Итак, когда мне нужно создавать новые типы данных, типы и т.д., и когда я должен использовать функции?

Спасибо.

4b9b3361

Ответ 1

Почему я не должен делать что-то простое и только определяя функции без определения новых типов данных и типов (с их экземпляры).

Почему? Вы можете просто определить:

checkState :: (a -> Bool) -> (a -> b) -> (a -> b) -> a -> b
checkState is_repairable repairs destroy a
    = if (is_repairable a) then repairs a else destroy a

Люди неправильно используют классы классов. Это не значит, что он идиоматичен.

Чтобы ответить на ваш более общий вопрос, вот некоторые эмпирические правила о том, когда использовать классы типов и когда их не использовать:

Используйте классы типов, если:

  • Существует только одно правильное поведение для заданного типа

  • Класс типа имеет связанные уравнения (т.е. "законы" ), что все экземпляры должны удовлетворять

Не используйте классы типов, если:

  • Вы пытаетесь просто использовать пространства имен. Для чего нужны модули и пространства имен.

  • Человек, использующий ваш тип, не может рассуждать о том, как он будет вести себя, не глядя на исходный код экземпляров

  • Вы обнаружите, что расширения, которые вы должны включить, выходят из-под контроля

Ответ 2

Вы можете часто использовать тип данных вместо типа-типа, например

data Repairable a = Repairable 
   { getRepairable :: a
   , isRepairable :: Bool
   , canBeRepairedWith :: [Tool] -> Bool  -- just to give an example of a function
   } 

Конечно, вам нужно передать это значение явно, но это может быть полезно, если у вас есть несколько вариантов (например, подумайте Sum и Product как можно больше Monoid для чисел). За исключением того, что у вас более или менее та же выразительность, что и для типа-класса.