Неопределенная переменная типа в поливариадном определении карри

Итак, я пытаюсь реализовать поливариадный ZipWithN, как описано здесь. К сожалению, код Paczesiowa, похоже, был скомпилирован с устаревшими версиями как ghc, так и HList, поэтому, пытаясь понять, как он работает, я также портировал его до самых последних версий обоих (ghc-7.8.3 и HList-0.3.4.1 в настоящее время). Это было весело.

В любом случае, я столкнулся с ошибкой, которую Google не помогает мне исправить на этот раз в определении посреднической функции. curryN', По идее, curryN' прост: он принимает натуральное число на уровне типа N (или, строго говоря, значение этого типа), и функция f чей первый аргумент является HList длины Nи возвращает N-Внутри функция, которая делает HList из своего первого N аргументы и возвращает f применяется к этому HList. Это curry, но поливариадный.

Он использует три вспомогательные функции / классы:

Первый ResultType/resultType, как я определил здесь. resultType принимает одну функцию в качестве аргумента и возвращает тип этой функции после применения ее к столько аргументов, сколько потребуется. (Строго говоря, опять же, он возвращает неопределенное значение этого типа).

Например:

ghci> :t resultType (++)
resultType (++) :: [a]
ghci> :t resultType negate
resultType negate :: (ResultType a result, Num a) => result

(Последний случай, потому что если a случается, функция типа x -> y, resultType должен был бы вернуть y, Так что это не идеально применимо к полиморфным функциям.)

Вторые два Eat/eat а также MComp/mcompопределяется вместе (вместе с curryN') в одном файле (вместе со сломанным curryN') вот так.

eatпервый аргумент - это значение, тип которого является натуральным числом Nи возвращает функцию, которая принимает N аргументы и возвращает их объединенные в HList:

ghci> :t eat (hSucc (hSucc hZero))
eat (hSucc (hSucc hZero)) :: x -> x1 -> HList '[x, x1]
ghci> eat (hSucc (hSucc hZero)) 5 "2"
H[5, "2"]

Насколько я могу сказать, это работает отлично. mcomp является поливариадной составной функцией. Требуется две функции, f а также g, где f принимает некоторое количество аргументов N, Возвращает функцию, которая принимает N аргументы, применяется f ко всем из них, а затем относится g в f, (Функция порядка параллелей (>>>) больше, чем (.))

ghci> :t (,,) `mcomp` show
(,,) `mcomp` show :: (Show c, Show b, Show a) => a -> b -> c -> [Char]
ghci> ((,,) `mcomp` show) 4 "str" 'c'
"(4,\"str\",'c')"

подобно resultType, он "ломается" на функциях, чьи возвращаемые типы являются переменными типа, но так как я планирую использовать его только на eat (чей конечный тип возврата просто HList), это должно работать (Пацезова, кажется, так считает, по крайней мере). И это так, если первый аргумент eat фиксированный:

\f -> eat (hSucc (hSucc hZero)) `mcomp` f

работает отлично.

curryN' однако определяется так:

curryN' n f = eat n `mcomp` f

Попытка загрузить это в ghci, однако, получает эту ошибку:

Part3.hs:51:1:
    Could not deduce (Eat n '[] f0)
      arising from the ambiguity check for ‘curryN'’
    from the context (Eat n '[] f,
                      MComp f cp d result,
                      ResultType f cp)
      bound by the inferred type for ‘curryN'’:
                 (Eat n '[] f, MComp f cp d result, ResultType f cp) =>
                 Proxy n -> (cp -> d) -> result
      at Part3.hs:51:1-29
    The type variable ‘f0’ is ambiguous
    When checking that ‘curryN'’
      has the inferred type ‘forall f cp d result (n :: HNat).
                             (Eat n '[] f, MComp f cp d result, ResultType f cp) =>
                             Proxy n -> (cp -> d) -> result’
    Probable cause: the inferred type is ambiguous
Failed, modules loaded: Part1.

Так ясно eat а также mcomp не играйте так хорошо, как хотелось бы. Между прочим, это значительно отличается от вида ошибки, которая mcomp (+) (+1) т, который жалуется на перекрывающиеся экземпляры для MComp,

В любом случае, попытка найти информацию об этой ошибке не привела меня к чему-то полезному - самым большим препятствием для моей собственной отладки было то, что я понятия не имел, что такое переменная типа. f0 даже, так как он не появляется ни в одной из сигнатур типов или контекстов, которые делает ghci.

Я думаю, что mcomp возникают проблемы с повторением eatполиморфный тип возвращаемого значения (даже несмотря на то, что это зафиксировано натуральным числом на уровне типа). Но если это так, я не знаю, как бы я это исправить.

Дополнительно (и странно для меня), если я пытаюсь объединить Part1.hs а также Part2.hs в один файл, я все еще получаю ошибку... но другой

Part3alt.hs:59:12:
    Overlapping instances for ResultType f0 cp
      arising from the ambiguity check for ‘curryN'’
    Matching givens (or their superclasses):
      (ResultType f cp)
        bound by the type signature for
                   curryN' :: (MComp f cp d result, Eat n '[] f, ResultType f cp) =>
                              Proxy n -> (cp -> d) -> result
        at Part3alt.hs:(59,12)-(60,41)
    Matching instances:
      instance result ~ x => ResultType x result
        -- Defined at Part3alt.hs:19:10
      instance ResultType y result => ResultType (x -> y) result
        -- Defined at Part3alt.hs:22:10
    (The choice depends on the instantiation of ‘cp, f0’)
    In the ambiguity check for:
      forall (n :: HNat) cp d result f.
      (MComp f cp d result, Eat n '[] f, ResultType f cp) =>
      Proxy n -> (cp -> d) -> result
    To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
    In the type signature for ‘curryN'’:
      curryN' :: (MComp f cp d result, Eat n [] f, ResultType f cp) =>
                 Proxy n -> (cp -> d) -> result
Failed, modules loaded: none.

Опять с загадочным f0 переменная типа Я признаю, что я немного над головой здесь со всей этой хакерской атакой, так что если кто-то может помочь мне выяснить, в чем именно заключается проблема, и, что более важно, как я могу ее исправить (если это так, надеюсь, возможно), я был бы невероятно благодарен.

Последнее замечание: причина того, что два файла здесь называются Part1 и Part3, состоит в том, что Part2 содержит некоторые вспомогательные функции, используемые в zipWithN, но нет curryN', По большей части они работают нормально, но есть пара странностей, о которых я мог бы спросить позже.

0 ответов

Другие вопросы по тегам