2012-04-27 2 views
4

Зачем стоит [Char] экземпляры Ord, но не для Enum?Почему нет строки для перечисления?

Prelude> let succ_a = "a" ++ [minBound::Char] 
Prelude> "a" < succ_a 
True 
Prelude> succ_a < "a " 
True 
Prelude> succ_a < succ_a ++ [minBound::Char] 
True 

Я думаю, что нет строки между «а» и succ_a - так почему бы не succ "a" == succ_a?

+0

На самом деле, я могу думать о многих строках между «а» и «аа». Там есть «a_» и «a__», «a____» и «a______» ... ad infinitum. («_» должно быть пробелом, кстати) – Ord

+0

Точка взята. Но см. Edit - «a» ++ [minBound :: Char] - который является «a \ NULL» - это> «a» и <любой из этих примеров – gcbenison

+7

Экземпляр «Enum», который вы предлагаете, не полезен , Перечисление, начинающееся с заданного значения, приведет к созданию потока более длинных строк символов «\ NULL», и не может быть предложен экземпляр «Enum», который полезен по той же причине, что реальные числа не рекурсивно перечислимы. –

ответ

15

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

Использование алфавита a..z для простоты, лексикографический порядок просто дает нам повторения первой буквы.

"", "a", "aa", "aaa", "aaaa", "aaaaa" ... 

Более полезный порядок перечисления строк по длине. Таким образом, мы получаем первую пустую строку, то все строки длиной 1, то все длины 2, и т.д.

"", "a", "b", ... "z", "aa", "ba", ... "za", "ab", ... "zz", "aaa", "baa" ... 

Это, по существу, такой же, как с перечислением чисел, с обратной цифры, поэтому, когда вы добраться до "zz" вы носите и получить "aaa", точно так же как, как вы получите от 99 до 100.

Однако, это было бы несовместимо с Ord например, для списков, которые используют лексикографический порядок.

2

Во-первых, вы ошибаетесь "а" и "аа":

Prelude> "a" < "aA" && "aA" < "aa" 
True 

Что следующая строка после того, как "Foo"? Это «fop»? Это "fooa?" Это «foo \ 0»?

+18

Это «бар», очевидно. –

+0

На самом деле я думаю, что это '' foo "++ [minBound :: Char]'. – gcbenison

4

Отказ от ответственности: Я мало знаю о Haskell.

Однако из http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Enum видно, что Enum должен поддерживать toEnum и fromEnum для преобразования из типа перечисления в Int и обратно. Как это работает для строк? Если succ_a = "a" ++ [minBound::Char], то любой Int отображает строку «a» с некоторым количеством добавленных к ней minBound::Char (или, что более реалистично, любой Int n отображает в список размером n, который содержит только minBound::Char). Таким образом, «b» не будет отображаться на какой-либо Int.

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