多变量咖喱定义中的模糊类型变量

时间:2014-08-15 03:28:55

标签: function haskell currying polyvariadic

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

无论如何,在中间函数curryN'的定义中,我遇到了谷歌没有帮我修复一次的错误。在概念上,curryN'很简单:它采用类型级自然数N(或严格来说,该类型的值),以及函数f,其第一个参数是长度为N的HList,并返回一个N - ary函数,该函数使HList脱离其第一个N参数,并返回应用于该HList的f。它是curry,但是是多变量的。

它使用三个辅助函数/类:

第一个是ResultType / resultType,因为我已定义hereresultType将一个函数作为参数,并在将该函数应用于所需的参数之后返回该函数的类型。 (严格地说,它再次返回该类型的未定义值)。

例如:

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

(后一种情况,因为如果a碰巧是类型x -> y的函数,则resultType必须返回y。所以它不适用于多态函数。)

后两个是Eat / eatMComp / mcomp,在一个文件中一起定义(以及curryN')(以及已损坏curryN'},如this

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是一个多变量组合函数。它需要两个函数fg,其中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无法通过eat的多态返回类型进行递归(即使这是由类型级自然数修复的)。但如果是这样的话,我不知道如何解决这个问题。

另外(对我来说很奇怪),如果我尝试将Part1.hsPart2.hs合并为一个file,我仍会收到错误...但是另一个错误

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 个答案:

没有答案