6

所以,我正在尝试实现一个多变量 ZipWithN,如此处所述。不幸的是,Paczesiowa 的代码似乎是用过时版本的 ghc 和 HList 编译的,所以在试图理解它是如何工作的过程中,我也一直在将它移植到这两个版本的最新版本(ghc- 7.8.3 和 HList-0.3.4.1)。这很有趣。

无论如何,我在中间函数的定义中遇到了一个谷歌没有帮助我修复的错误curryN'。从概念上讲,curryN'很简单:它接受一个类型级别的自然数N(或者,严格来说,该类型的值)和一个函数f,其第一个参数是一个长度为 HList 的函数N,并返回一个N-ary 函数,该函数接受一个 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碰巧是 type 的函数x -> y, resultType 必须返回y。所以它并不完美地应用于多态函数。)

后两个是Eat/eatMComp/ ,像这样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)上使用它,它应该可以工作(至少 Paczesiowa 似乎是这么认为的)。它确实如此,如果第一个参数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.

很清楚eatmcomp不要像我希望的那样玩得那么好。顺便说一句,这与给出的那种错误有很大不同mcomp (+) (+1),后者抱怨MComp.

无论如何,尝试查找有关此错误的信息并没有让我找到任何有用的信息 - 我自己调试的最大障碍是我什至不知道类型变量f0是什么,因为它没有出现在任何类型中ghci 推断的签名或上下文。

我最好的猜测是,mcomp通过 's 的多态返回类型进行递归时遇到了麻烦eat(即使它是由类型级自然数固定的)。但如果是这样的话,我不知道我将如何解决它。

另外(对我来说很奇怪),如果我尝试将其合并Part1.hsPart2.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类型变量。我承认我对所有这些 typehackery 有点不知所措,所以如果有人能帮我弄清楚这里到底是什么问题,更重要的是,我该如何解决它(如果是的话,希望,可能),我将非常感激。

最后说明:这里的两个文件之所以叫Part1和Part3,是因为Part2里面有一些辅助函数用到了zipWithN,而没有curryN'。在大多数情况下,它们工作正常,但我稍后可能会问一些奇怪的问题。

4

0 回答 0