6

だから、ここで説明されているように、多変量の ZipWithN を実装しようとしています。残念ながら、Paczesiowa のコードは ghc と HList の両方の古いバージョンでコンパイルされているようです。そのため、それがどのように機能するかを理解しようとする過程で、両方の最新バージョン (ghc-現時点では 7.8.3 および HList-0.3.4.1)。楽しかったです。

とにかく、中間関数の定義で、Googleが一度も修正するのを手伝ってくれないというバグに遭遇しましたcurryN'。概念curryN'は単純です: 型レベルの自然数N(厳密に言えば、その型の値) と、f最初の引数が length の HList である関数を取り、make HList を取る -ary 関数をN返します。N最初のN引数のうち、そのfHList に適用されたものを返します。ですcurryが、多変量です。

3 つのヘルパー関数/クラスを使用します。

ここで定義したように、最初はResultType/です。 単一の関数を引数として取り、その関数を必要な数の引数に適用した後、その関数の型を返します。(厳密に言えば、その型の未定義の値を返します)。resultTyperesultType

例えば:

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

(後者のケースは、aたまたま type の関数だった場合x -> y、 resultType は を返さなければならないためですy。したがって、多相関数に完全に適用されるわけではありません。)

2 番目の 2 つはEat/eatMComp/で、こののように (壊れた とともに) 1 つのファイルでmcomp一緒に (とともに) 定義されます。curryN'curryN'

eatの最初の引数は、型が自然数の値であり、引数を受け取り、それらを組み合わせて HList に返すN関数を返します。N

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多変量構成関数です。これは と の 2 つの関数をf取りgfいくつかの引数を取りますNN引数を取り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.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型変数で。私はこのタイプハッカーのすべてについてここで少し頭を悩ませていることを認めます.うまくいけば、可能です)、私は信じられないほど感謝しています.

最後の注意: ここで 2 つのファイルが Part1 と Part3 と呼ばれる理由は、Part2 には で使用されるいくつかの補助関数が含まれていますが、 では使用されてzipWithNいないためcurryN'です。ほとんどの場合、それらは正常に機能しますが、後で尋ねるかもしれない奇妙な点がいくつかあります。

4

0 に答える 0