Haskell Преобразование из массива в распакованный массив нарушает правила перезаписи - PullRequest
1 голос
/ 12 февраля 2012

Я пытаюсь преобразовать мою программу из Data.Array в Data.Array.Unboxed.

В качестве краткого примечания: в нескольких местах указано, что я могу изменить "Array" на "UArray"код и ДОБАВИТЬ импорт Data.Array.Unboxed, однако я не смешиваю оба типа массивов, поэтому я просто импортировал Data.Array.Unboxed вместо Data.Array, достаточно ли этого?переключите следующие разрывы правила перезаписи:

{-# RULES
    "applyWindow/applyWindow" forall win1 win2 image. 
                                     applyWindow win1 
                                                 (applyWindow win2 
                                                 image) = 
                                     applyWindow (indexMult win1 win2) 
                                                            image
  #-}

Здесь win1 win2 и изображение должны быть UArrays.Однако это не компилируется с последующими ошибками.

FIPlib/Core.hs:229:99:
    Ambiguous type variables `e0', `a0' in the constraint:
      (IArray a0 e0) arising from a use of `applyWindow'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

FIPlib/Core.hs:229:99:
    Ambiguous type variables `e0', `a2' in the constraint:
      (IArray a2 e0) arising from a use of `applyWindow'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

FIPlib/Core.hs:229:112:
     Ambiguous type variables `e0', `a1' in the constraint:
      (IArray a1 e0) arising from a use of `indexMult'
    Probable fix: add a type signature that fixes these type variable(s)
    In the first argument of `applyWindow', namely
      `(indexMult win1 win2)'
    In the expression: applyWindow (indexMult win1 win2) image
    When checking the transformation rule "applyWindow/applyWindow"

Что делает это неоднозначным?Почему происходит сбой при работе с Data.Array?

Ответы [ 2 ]

3 голосов
/ 12 февраля 2012

Проблема в том, что Data.Array.Unboxed реэкспортирует Data.Array.IArray, и, следовательно, класс IArray для интерфейса неизменяемого массива, но Data.Array этого не делает (он даже не импортирует его). Поэтому, если вы используете такие функции, как bounds, accumArray, array и т. Д. Только с импортированным Data.Array, они являются мономорфными в типе массива, поэтому не возникает никакой неоднозначности (полиморфизм в типе элемента, очевидно, не представляет проблема здесь, это было бы с подходящими ограничениями класса типа). Но если вы импортируете Data.Array.Unboxed, все эти функции получают ограничение IArray a e, и, таким образом, перезапись может включать разные типы массивов, что приводит к разрывам. Вам необходимо исправить типы с помощью сигнатур типов, функций или правил. Как именно это решить, я не могу сказать, не увидев код.

Примечание: проверка типов изменилась с 7.4, с ghc-7.4.1, код без правила не компилируется без сигнатур типов при импорте Data.Array.Unboxed.

Чтобы исправить типы, чтобы правило не попадало в неоднозначность, необходимо указать сигнатуры типов

  • на верхнем уровне, до applyWindow,
  • к двум локальным привязкам paddedImage и filteredPaddedImage.

Вероятно, желательно и наиболее разумно, чтобы все задействованные массивы имели одинаковый тип, который может быть

  1. мономорфный тип, скажем UArray (Int,Int) Int (тип элемента также может быть Word, ...)
  2. тип, мономорфный в типе массива и полиморфный в типе элемента
  3. тип плойморфизма в обоих

Для 1. вам просто нужно добавить подписи applyWindow :: T -> T -> T и xxImage :: T (где T - требуемый тип). Для 2. вам нужно добавить два языковых расширения, FlexibleContexts и ScopedTypeVariables, тогда applyWindow получит подпись

applyWindow :: forall e. (Num e, IArray UArray e)
            => UArray (Int,Int) e -> UArray (Int,Int) e -> UArray (Int,Int) e

и локальные привязки получат подпись xxImage :: UArray (Int,Int) e. FlexibleContexts необходим, чтобы разрешить вхождение UArray в constarint, и ScopedTypeVariables необходимо, чтобы ввести тип элемента в область видимости, чтобы paddedImage и filteredPaddedImage могли вообще получать сигнатуры типов. Для 3. требуется только ScopedTypeVariables, тогда сигнатура типа applyWindow будет

applyWindow :: forall a e. (Num e, IArray a e) => ...

Другой метод для принудительного использования всех массивов одного типа - использование asTypeOf или помещение их всех в список (неиспользуемая локальная привязка), но предпочтительнее использовать сигнатуры типа IMO.

Как только все типы зафиксированы (они не обязательно должны быть одинаковыми, но тип локальных привязок должен определяться типом аргумента и результата, возможно, только типами аргумента), правило должно проверять тип. (Также может потребоваться исправить типы в indexMult.)

2 голосов
/ 12 февраля 2012

Я получил точно такое же сообщение об ошибке (об IArray и т. Д.) При попытке запустить этот код без явной сигнатуры типа для массива (в данном случае UArray Int Bool), только с Data.Array.Unboxed импорт.Когда я добавил подпись, все было в порядке.Может быть, это вам тоже поможет.

...