19

xml-lens(パッケージから) lens 引数を指定して、関数をリファクタリングしようとしています。型量指定子について何かが欠けています。ここで何が起こっているのですか?

*Main> let z name = listToMaybe $ pom ^.. root ./ ell name . text
*Main> :t z
z :: Text -> Maybe Text
*Main> let z name l = listToMaybe $ pom ^.. l ./ ell name . text

<interactive>:13:38:
    Couldn't match expected type ‘(Element -> f Element)
                                  -> Document -> f Document’
                with actual type ‘t’
      because type variable ‘f’ would escape its scope
    This (rigid, skolem) type variable is bound by
      a type expected by the context:
        Applicative f => (Element -> f Element) -> Document -> f Document
      at <interactive>:13:38-57
    Relevant bindings include
      l :: t (bound at <interactive>:13:12)
      z :: Text -> t -> Maybe Text (bound at <interactive>:13:5)
    In the first argument of ‘(./)’, namely ‘l’
    In the second argument of ‘(^..)’, namely ‘l ./ ell name . text’

興味深いことに、この署名は機能します。

textFrom :: Text -> Document -> Lens' Document Element -> Maybe Text
textFrom name pom ln = listToMaybe $ pom ^.. ln ./ ell name . text
4

1 に答える 1

14

ここでの問題は、レンズやxml-lens直接ではありません。上位型推論の問題です。

簡略化されたテスト ケース

まず、質問の問題のあるタイプを使用して最小限の例を作成しましょう。あなたのコードでは、 ;を期待するlfunction に渡しています。残りの機能を置き換えて省略しています。(./)Traversable(./)g

g :: Traversal s t a b -> String
g = undefined

-- f :: Traversal s t a b -> String
f l = g l

エラー:

Couldn't match expected type `(a0 -> f b0) -> s0 -> f t0'
            with actual type `t'
  because type variable `f' would escape its scope
This (rigid, skolem) type variable is bound by
  a type expected by the context:
    Control.Applicative.Applicative f => (a0 -> f b0) -> s0 -> f t0
  at SO27247620.hs:14:7-9
Relevant bindings include
  l :: t (bound at SO27247620.hs:14:3)
  f :: t -> String (bound at SO27247620.hs:14:1)
In the first argument of `g', namely `l'
In the expression: g l

問題と同様に、型シグネチャのコメントを外すと修正されます。

型シグネチャを展開して理由を見てみましょう。

type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t

f :: (forall f. Applicative f => (a-> f b) -> s -> f t) -> String

ここでのオチは単純fに、上位の型を持つ、つまりネストされたforall;を含むということです。または のいずれかRankNTypesを記述する必要があります。fg

上位型の推論

上位の型の型推論は、常に可能であるとは限りません。あなたの問題は、「GHCはこの上位の型を推測できない」に要約されます。それに対する答えは基本的に「GHCはそうできるとは約束していません」です。

具体的には、GHC が推論と高ランクの型に関して行う文書化された仮定の 1 つは、GHC 7.8.3 docsからの次のとおりです。

ラムダ バインドまたはケース バインド変数 x の場合、プログラマが明示的な多相型を x に提供するか、GHC の型推論で x の型に forall がないと仮定します。

この例では、変数lはラムダ バインドされており、明示的なポリモーフィック型はありません。したがって、GHC はその型 (エラーメッセージが呼び出すt) には forall がないと仮定します。それを統一しようとすると、forall f. (a0 -> f b0) -> s0 -> f t0その仮定に違反します。

fスコープをエスケープする型変数に関するビットfは、 forall が必要であることを示しています。

ちなみに、実際の最小限の例は次のとおりです。

g' :: (forall a. a) -> b
g' = undefined

f' = \x -> g' x
于 2014-12-04T19:00:21.363 に答える