Haskell: Почему (+), (-) являются частью класса типов Num?

Из ghci:

Prelude> :i Num                              
class Num a where                            
  (+) :: a -> a -> a                         
  (-) :: a -> a -> a                         
  (*) :: a -> a -> a                         
  negate :: a -> a                           
  abs :: a -> a                              
  signum :: a -> a                           
  fromInteger :: Integer -> a                
        -- Defined in `GHC.Num'              
instance Num Word -- Defined in `GHC.Num'    
instance Num Integer -- Defined in `GHC.Num' 
instance Num Int -- Defined in `GHC.Num'     
instance Num Float -- Defined in `GHC.Float' 
instance Num Double -- Defined in `GHC.Float'

Почему (+), (-) часть класса Num для начала?

Например, вы можете легко определить класс этого типа:

class Plus a where
     (+) :: a -> a -> a

А потом пусть:

instance Plus [] where
    (+) = (++)

И вы также можете определить их для наборов, чтобы означать множество объединений, или добавить (-) к классу типов, чтобы означать множество различий... И нет смысла определять signum в списке.

Конечно, я мог бы создать свой собственный класс типов, который использует (|+|) вместо этого - но почему эти операторы зарезервированы в haskell только для Num?

Так почему был сделан этот выбор? Это связано с наследством или никто не хотел этого?

2 ответа

Решение

Во многом это связано с историческими причинами, но есть и математические. Например, уже есть математические имена для структур, которые поддерживают бинарные операторы. Наиболее часто используемым является моноид, который вы можете использовать в Data.Monoid, Этот класс типов определяет функцию mappend и значение mempty, эквивалент элемента идентичности для mappendи есть псевдоним оператора для mappend называется <>, Списки и многие другие объекты образуют моноиды, а числа фактически образуют 2, с + и с *где элементы идентичности равны 0 и 1 соответственно. Структуры, которые имеют идентичность, ассоциативную двоичную операцию и инверсию для этой операции (например, вычитание является обратным к сложению), называются группами (не являются частью стандартной библиотеки), а структуры, которые образуют группу под одним оператором и моноид под вторым оператором называется кольцами. Эти объекты являются основой для алгебраических структур / классов абстрактной алгебры.

Эти математические конструкции несколько сложны для реализации в Haskell, по крайней мере, очень хорошо. Есть перекрывающиеся экземпляры для Monoid для всех Num типы с + а также *и для некоторых числовых типов есть Group перекрываются, если / может быть определено так, что деление на 0 хорошо определено (некоторые структуры могут это позволить). Эти перекрывающиеся экземпляры приводят к появлению множества новых типов, которые затрудняют ежедневную работу. Num Здесь помогает typeclass, поскольку он предоставляет полезный интерфейс для управления и выполнения операций над числами, который прост в использовании в реальном мире кода, а не только в научных кругах. Были попытки ввести более математическую версию PreludeИ некоторые люди используют их с переменным успехом, но ваш средний Хаскеллер предпочел бы отказаться от математической чистоты для более практичного интерфейса.

Короче говоря, Num Класс типов определен таким образом по историческим причинам, а также по очень практическим причинам. Более строгая математическая конструкция громоздка, и для многих типов просто использовать Data.Monoid"s <> Оператор идеален.

Я предполагаю, что они намеревались Num отражать математическую природу чисел, а не какую-то более общую структуру. Операция в Num В основном это те, которые поддерживают абстрактную математическую структуру, называемую кольцом, из которых целые числа (и любые их расширения) являются ярким примером.

Поскольку Haskell позволяет вам определять свои собственные операторы, вы можете настроить свои собственные обозначения. Затем, когда другие прочитают ваш код, они смогут сказать, что вы работаете с чем-то, что не NumБер, как, но, возможно, более общий.

В прелюдии Haskell есть много неудачных исторических решений, которые нельзя исправить, поскольку они могут нарушить совместимость. Однако, ИМХО, базовый дизайн Num Класс типов и операторов это звук.

Другие вопросы по тегам