Предположим, я хочу определить тип 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
) и ==
.
Поскольку все функции могут сопоставлять их аргументы, они всегда могут обойти любого оператора ==
. Почему Хаскелл просто принял представление в памяти как определение равенства? Таким образом, все типы становятся тривиально равными.
На самом деле равенство подразумевается самой концепцией функции: графом, который дает равные выходы при заданных равных входах. Поэтому не имеет смысла говорить о функции на типе, который не является равнозначным.
Я не хочу 'Green' моих' данных Color = Red | Зеленый | Синий "должен быть равен True. По крайней мере, неявно. – arrowd
Компилятор может сказать, что они не равны: у них нет одинакового типа. –
«Поскольку все функции могут сопоставлять их аргументы, они не могут, если тип аргумента не экспортирует его конструкторы. – sepp2k