7

私は以下のような機能を持っています:

    foo :: Int -> a -> [a]
    foo n v = bar n
      where
        bar :: Int -> [a]
        bar n = take n $ repeat v

ghci を使用すると、次のエラーが報告されます。

    Couldn't match type `a' with `a1'
          `a' is a rigid type variable bound by
              the type signature for foo :: Int -> a -> [a] at hs99.hs:872:1
          `a1' is a rigid type variable bound by
              the type signature for bar :: Int -> [a1] at hs99.hs:875:9
    Expected type: [a1]
        Actual type: [a]
    In the expression: take n $ repeat v
    In an equation for `bar': bar n = take n $ repeat v

bar の型宣言を削除すると、コードはエラーなしでコンパイルできます。では、ここで bar の適切な型宣言は何ですか? また、bar の型宣言は bar の定義 (foo の型にバインドされている) よりも一般的であるため、エラーが発生するのはなぜですか?

助けてくれてありがとう!

4

2 に答える 2

10

aイン_

foo :: Int -> a -> [a]

そしてaイン

    bar :: Int -> [a]

同じ名前の異なる型変数です。

期待どおりの動作を得るには、ScopedTypeVariables 拡張機能をオンにし (たとえば{-# LANGUAGE ScopedTypeVariables #-}、ソース ファイルの先頭に挿入することにより)、型シグネチャを に変更しますfoo

foo :: forall a. Int -> a -> [a]

ScopedTypeVariables が有効になっていない場合、元のコードが次のように記述されているかのようになります。

foo :: forall a. Int -> a -> [a]
foo n v = bar n
  where
    bar :: forall a. Int -> [a]
    bar n = take n $ repeat v

の型注釈を省略した場合、ghci が暗黙的に ScopedTypeVariables を使用すると言うのは正しくありませんbar

代わりに、bar型 ghci との競合に対して指定した型注釈は、型 ghci がbar持つことができないことを ghci が知っている型を持っていると主張しています。

型注釈を削除すると、競合が削除されます。

ScopedTypeVariables は、指定した型注釈の意味を変更します。ghc が型を推論する方法には影響しません。

于 2012-05-22T20:07:53.707 に答える
2

そして、このスレッドにも良い説明があることがわかりました: http://www.haskell.org/pipermail/haskell-cafe/2008-June/044617.html

于 2012-05-23T07:41:38.800 に答える