2016-09-24 3 views
-2

Предположим, я хочу определить тип Mod4 целых чисел по модулю 4. В конце концов, Int is Mod2^64. Один очевидный способ, которым я мог бы этоПочему класс Eq существует?

data Mod4 = ZeroMod4 | OneMod4 | TwoMod4 | ThreeMod4 

Однако я также мог бы сделать это

data Mod4 = Mod4 Integer 

instance Eq Mod4 where 
    (Mod4 x) == (Mod4 y) = (x-y) `mod` 4 == 0 

Но тогда эта функция является проблематичным:

f :: Mod4 -> Mod4 
f (Mod4 x) = if x < 20 then Mod4 0 else Mod4 1 

f (Mod4 16) отличается от f (Mod4 20), в то время как те два Аргументы: ==. Таким образом, я получаю два вида равенства: представление в памяти ( Mod4 16 отличается от Mod4 20) и ==.

Поскольку все функции могут сопоставлять их аргументы, они всегда могут обойти любого оператора ==. Почему Хаскелл просто принял представление в памяти как определение равенства? Таким образом, все типы становятся тривиально равными.

На самом деле равенство подразумевается самой концепцией функции: графом, который дает равные выходы при заданных равных входах. Поэтому не имеет смысла говорить о функции на типе, который не является равнозначным.

+0

Я не хочу 'Green' моих' данных Color = Red | Зеленый | Синий "должен быть равен True. По крайней мере, неявно. – arrowd

+1

Компилятор может сказать, что они не равны: у них нет одинакового типа. –

+7

«Поскольку все функции могут сопоставлять их аргументы, они не могут, если тип аргумента не экспортирует его конструкторы. – sepp2k

ответ

10

Почему Хаскелл не принял представление в памяти как определение равенства? Таким образом, все типы становятся тривиально равными.

Nope. Вы не можете сравнивать значения типа Integer -> Bool. В общем, функции нельзя сравнивать.

Назад к доске. Как разработать равенство на типизированном языке?

Один из вариантов - дать (==) :: a -> a -> Bool и выдать исключение, если a является функцией. См. Ocaml.

Другой вариант заключается в том, чтобы типы разделов в уравновешенном/неравномерном виде. Это eqtype в SML.

Другим, но связанным, вариантом является выражение «eq-способность» как ограничение на полиморфизм. Eq в Haskell.

Теперь, Eq, возможно, было более особенным. Например. вы не можете определить свои экземпляры самостоятельно, и вы должны использовать deriving Eq, как и сейчас, как работает Typeable. Дизайнеры Haskell вместо этого позволяют пользователям определять свою собственную функцию сравнения. Пользователи могут знать некоторые «умные» способы. Например. чтобы сравнить 10-полевую запись, начните с сравнения обычно разных полей и сравните обычно-равных позже, пытаясь повысить эффективность.

Обратите внимание: если мы не экспортируем конструктор типа данных, мы можем сделать равенство эквивалентом и по-прежнему быть полезным. Например. Data.Set.Set приравнивает разные (сбалансированные) деревья, когда они представляют один и тот же набор, но экспортируемый интерфейс никогда не нарушает эквивалентность, поэтому равенство выглядит как равенство извне.

Так что не имеет смысла говорить о функции типа, который не является равнозначным.

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

+0

«Когда предикат равенства не является вычислимым» относится ли это к таким типам функций, как 'Int -> Bool'? Действительно, мы имеем функции функций. Или, может быть, более сложный случай, например [презентация группы] (https://en.wikipedia.org/wiki/Presentation_of_a_group)? Я считаю, что очень сложно вычислить, являются ли два групповых представления изоморфными. –

+0

@ V.Semeria Да, при заданных произвольных 'f, g :: Integer -> Bool' мы не можем решить, являются ли они одной и той же функцией. См. Любую книгу/курс теории вычислимости/рекурсии. Следует отметить, что, например, '\ x -> 2 * x' и' \ x -> x + x' - это одна и та же функция, даже если они, вероятно, имеют другое представление в памяти. – chi

+6

@ V.Semeria, представленный здесь пример 'Data.Set', представляет собой очень распространенный случай. * Большинство * интересных структур данных имеют некоторое количество «избыточности», позволяя более одного конкретного представления одного и того же абстрактного объекта. 'Data.Set',' Data.Map', 'Data.Sequence', типы графов в' fgl', канаты, кучи, векторные срезы, всевозможные варианты B-дерева, функциональные очереди, deques, ограничения на выходные ограничения , catenable deques, monoidal finger trees и т. д., все имеют неструктурное равенство. – dfeuer

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