#arrays #haskell #range
#массивы #haskell #диапазон
Вопрос:
Мой код вставлен сюда. Ниже приведен мой сеанс отладки ghci. Я все еще не понимаю, почему он имеет диапазон (0, -193459561), когда привязка ‘len’ равна 90570.
*Main> :break 125
Breakpoint 4 activated at SVMCF.hs:125:13-86
*Main> :trace main
Stopped at SVMCF.hs:125:13-86
_result :: UA.Array Int [User] = _
len :: Int = 90570
rts :: [RTuple] = (1,1,5.0) : (1,2,3.0) : (1,3,4.0) : (1,4,3.0) :
(1,5,3.0) : ....
[SVMCF.hs:125:13-86] *Main> :lis
124 points :: A.Array Int [Int]
125 points = assert (len > 0) $ A.listArray (1::Int, len) $ map ((u,i,r) -> [u,i]) rts
126 values :: UA.UArray Int Double
[SVMCF.hs:125:13-86] *Main> :ste
Stopped at SVMCF.hs:125:13-28
_result :: UA.Array Int [User] -> UA.Array Int [User] = _
len :: Int = 90570
[SVMCF.hs:125:13-28] *Main> :ste
Stopped at SVMCF.hs:125:21-27
_result :: Bool = _
len :: Int = 90570
[SVMCF.hs:125:21-27] *Main> :ste
Stopped at SVMCF.hs:125:32-86
_result :: UA.Array Int [User] = _
len :: Int = 90570
rts :: [RTuple] = (1,1,5.0) : (1,2,3.0) : (1,3,4.0) : (1,4,3.0) :
(1,5,3.0) : ....
[SVMCF.hs:125:32-86] *Main> :ste
Stopped at SVMCF.hs:125:32-56
_result :: [[User]] -> UA.Array Int [User] = _
len :: Int = 90570
[SVMCF.hs:125:32-56] *Main> :lis
124 points :: A.Array Int [Int]
125 points = assert (len > 0) $ A.listArray (1::Int, len) $ map ((u,i,r) -> [u,i]) rts
126 values :: UA.UArray Int Double
[SVMCF.hs:125:32-56] *Main> len
90570
[SVMCF.hs:125:32-56] *Main> :ste
Stopped at SVMCF.hs:125:60-86
_result :: [[User]] = _
rts :: [RTuple] = (1,1,5.0) : (1,2,3.0) : (1,3,4.0) : (1,4,3.0) :
(1,5,3.0) : ....
[SVMCF.hs:125:60-86] *Main> :ste
*** Exception: Ix{Int}.index: Index (1) out of range ((1,-193459561))
Комментарии:
1. Это действительно выглядит странно. Моей первой мыслью было какое-то арифметическое переполнение. Значение Int равно 32 битам на 32-разрядной машине и 64 битам на 64-разрядной машине. Что вычисляет maxBound :: Int? Однако я не могу найти какой-либо прямой взаимосвязи между 90570 и -193459561
2. Можете ли вы также вставить тестовые данные (
ua.*
)? Я предполагаю, чтоSVM
модуль поставляется изsvm
пакета.3. Да, модули SVM поставляются из пакета svm, но я добавляю параметрический полиморфизм к этому модулю, поэтому код не сможет скомпилироваться, если вы используете пакет cabal svm. Данные ua.* взяты из набора данных stadard movielens, я должен был вставить ua. тест в hpaste.org/47496/movielens_uatest , но ua. база слишком велика для вставки. Могу ли я отправить вам все свои файлы по электронной почте?
4. Если второй файл слишком велик для вставки, вы можете загрузить его, например, в rapidshare. Если рассматриваемый набор данных доступен онлайн, вы можете просто предоставить ссылку.
5. Ну, я думаю, ghc использует 31 бит и 63 бита соответственно. Один бит для сборки мусора. Хотя я могу ошибаться.
Ответ №1:
Я подозреваю, что исключение index out of range вызывается не в том выражении, в котором вы думаете, что это так!
Данные.Array.listArray (1,-10) [2,3,4,5]
не генерирует никакого исключения, он просто выдает вам пустой массив. Также обратите внимание на номера столбцов в последнем отладочном сообщении:
Остановлено на SVMCF.hs:125:60-86
от 60 до 86 — это то, map ((u,i,r) -> [u,i]) rts
в котором, очевидно, не происходит никакой индексации: ни в map, ни в его первом аргументе ее определенно нет, и rts
она тоже выглядит чистой, поскольку поступает прямо из ua.base
через Parsec.
Поскольку Haskell разрешено быть довольно свободным в отношении порядка вычисления, возможно, что исключение генерируется сокращением в совершенно другом выражении. Вы уверены, что все остальные параметры, которые вы передаете в SVM, настроены правильно? В частности, учитывая, что вы используете Int
-индексированные массивы, вы уверены, что ни в одном массиве не происходит переполнения целых чисел? Являются ли какие-либо из ваших наборов данных, например, 4101507735 или 8396475031 записями, длинными, потому что они переполняются до -193459561 как Int
).
:history
Дает ли вам команда в отладчике GHCi какую-либо дополнительную информацию?
Комментарии:
1. Вы правы. Наконец, я обнаружил, что это переполнение индекса Int, и исходный код отсутствует в вставленном здесь коде. Хотя я, наконец, решил эту проблему, я думаю, что этот опыт заставляет меня думать, что отлаживать код на haskell сложно.