2016-01-13 2 views
1

От GHCI:Haskell: Почему (+), (-) часть Num typeclass?

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. Эта typeclass определяет функцию mappend и значение mempty, эквивалент элемента идентификации для mappend, и имеется операторский псевдоним для mappend, называемый <>. Списки и многие другие объекты образуют моноиды, а числа фактически образуют 2, с + и с *, где элементы идентичности равны 0 и 1 соответственно. Структуры, которые имеют идентичность, ассоциативную двоичную операцию и обратную для этой операции (вычитание является обратным добавлению, например), называются группами (а не частью стандартной библиотеки) и структурами, которые образуют группу под одним оператором и моноид под вторым оператором называются кольцами. Эти объекты являются основой для алгебраических структур/абстрактных классов алгебр.

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

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

+0

Haskell, практическое использование: P? Я думал, что это для размышлений только ^, - – Centril

+0

К сожалению, 'signum' (что за черт был даже предназначен?) И' abs' (который имеет неправильный тип, который действительно полезен для сложных чисел). К сожалению, представления с плавающей запятой - это экземпляры 'Num', несмотря на то, что они не очень похожи на числа. Другим неудачным фактом является то, что натуральные числа вообще не поддерживают '(-)' или 'отрицать'. – dfeuer

+0

Я думаю, что основным аргументом является то, что 'Num' был вызван прежде всего практическими проблемами. Синтаксис в основном идентичен другим языкам, и он работает исправно большую часть времени для большинства распространенных типов и видов использования. К сожалению, он разбивается на крайние случаи. Я не согласен, что печально, что представления с плавающей запятой являются экземплярами 'Num'; скорее я бы предположил, что некоторые из вариантов IEEE754 являются неудачными. –

1

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

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

В прелюдии Haskell существует много неудачных исторических дизайнерских решений, которые не могут быть исправлены, поскольку они нарушают совместимость. Тем не менее, IMHO, базовый дизайн модели и операторов Num звучит.

Смежные вопросы